Coverage Report

Created: 2026-11-11 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/duckdb/extension/json/json_functions/json_create.cpp
Line
Count
Source
1
#include "duckdb/common/vector/array_vector.hpp"
2
#include "duckdb/common/vector/flat_vector.hpp"
3
#include "duckdb/common/vector/list_vector.hpp"
4
#include "duckdb/common/vector/map_vector.hpp"
5
#include "duckdb/common/vector/union_vector.hpp"
6
#include "duckdb/common/vector/struct_vector.hpp"
7
#include "duckdb/execution/expression_executor.hpp"
8
#include "duckdb/function/cast/cast_function_set.hpp"
9
#include "duckdb/function/cast/default_casts.hpp"
10
#include "duckdb/function/function_binder.hpp"
11
#include "duckdb/function/scalar/strftime_format.hpp"
12
#include "duckdb/planner/expression/bound_cast_expression.hpp"
13
#include "duckdb/planner/expression/bound_constant_expression.hpp"
14
#include "duckdb/planner/expression/bound_function_expression.hpp"
15
#include "duckdb/planner/expression/bound_reference_expression.hpp"
16
#include "duckdb/planner/expression/bound_parameter_expression.hpp"
17
#include "duckdb/common/serializer/deserializer.hpp"
18
#include "duckdb/common/serializer/serializer.hpp"
19
#include "json_common.hpp"
20
#include "duckdb/main/client_context.hpp"
21
#include "duckdb/main/context.hpp"
22
#include "json_functions.hpp"
23
#include "json_geojson.hpp"
24
25
namespace duckdb {
26
27
static constexpr const char *JSON_COPY_TO_JSON_INTERNAL_NAME = "__internal_json_copy_to_json";
28
static constexpr const char *JSON_COPY_TO_GEOJSON_INTERNAL_NAME = "__internal_json_copy_to_geojson";
29
30
struct StructNames {
31
0
  void Insert(const string &name) {
32
0
    values[name] = make_uniq<Vector>(Value(name), count_t(0ULL));
33
0
  }
34
35
0
  StructNames Copy() const {
36
0
    StructNames result;
37
    // Have to do this because we can't implicitly copy Vector
38
0
    for (const auto &kv : values) {
39
      // The vectors are const vectors of the key value
40
0
      result.values[kv.first] = make_uniq<Vector>(Value(kv.first), count_t(0ULL));
41
0
    }
42
0
    return result;
43
0
  }
44
45
0
  bool Equals(const StructNames &other) const {
46
0
    if (values.size() != other.values.size()) {
47
0
      return false;
48
0
    }
49
0
    for (const auto &kv : values) {
50
0
      if (other.values.find(kv.first) == other.values.end()) {
51
0
        return false;
52
0
      }
53
0
    }
54
0
    return true;
55
0
  }
56
57
private:
58
  unordered_map<string, unique_ptr<Vector>> values;
59
};
60
61
struct JSONCreateFunctionData : public FunctionData {
62
public:
63
  explicit JSONCreateFunctionData(StructNames const_struct_names_p)
64
0
      : const_struct_names(std::move(const_struct_names_p)) {
65
0
  }
66
0
  unique_ptr<FunctionData> Copy() const override {
67
0
    return make_uniq<JSONCreateFunctionData>(const_struct_names.Copy());
68
0
  }
69
0
  bool Equals(const FunctionData &other_p) const override {
70
0
    return true;
71
0
  }
72
73
public:
74
  // Const struct name vectors live here so they don't have to be re-initialized for every DataChunk
75
  StructNames const_struct_names;
76
};
77
78
//! How a GEOMETRY value is represented in JSON. WKT is the default so that plain JSON output is unchanged;
79
//! COPY ... TO ... (FORMAT GEOJSON) selects GEOJSON. A global setting could flip the default later.
80
enum class JSONGeometryFormat : uint8_t { WKT, GEOJSON };
81
82
struct JSONCopyFormatOptions {
83
  JSONGeometryFormat geometry_format = JSONGeometryFormat::WKT;
84
  mutable optional_ptr<StrfTimeFormat> date_format;
85
  mutable optional_ptr<StrfTimeFormat> timestamp_format;
86
  mutable optional_ptr<Context> context;
87
  optional_ptr<const Expression> timestamptz_format_expression;
88
  optional_ptr<const Expression> timestamptz_ns_format_expression;
89
};
90
91
0
static JSONGeometryFormat ParseGeometryFormat(const Value &value) {
92
0
  if (value.IsNull()) {
93
0
    return JSONGeometryFormat::WKT;
94
0
  }
95
0
  const auto format = StringUtil::Lower(StringValue::Get(value));
96
0
  if (format == "wkt") {
97
0
    return JSONGeometryFormat::WKT;
98
0
  }
99
0
  if (format == "geojson") {
100
0
    return JSONGeometryFormat::GEOJSON;
101
0
  }
102
0
  throw InvalidInputException("Invalid value \"%s\" for json_geometry_format, expected 'wkt' or 'geojson'",
103
0
                              StringValue::Get(value));
104
0
}
105
106
0
void JSONFunctions::ValidateGeometryFormat(ClientContext &, SetScope, Value &parameter) {
107
0
  ParseGeometryFormat(parameter);
108
0
}
109
110
//! GEOMETRY is written as WKT unless the json_geometry_format setting says otherwise. COPY ... TO ...
111
//! (FORMAT GEOJSON) writes GeoJSON regardless, by overriding this afterwards.
112
0
static JSONGeometryFormat ClientGeometryFormat(Context &context) {
113
0
  Value value;
114
0
  if (!context.TryGetCurrentSetting("json_geometry_format", value)) {
115
0
    return JSONGeometryFormat::WKT;
116
0
  }
117
0
  return ParseGeometryFormat(value);
118
0
}
119
120
0
static JSONCopyFormatOptions ClientFormatOptions(Context &context) {
121
0
  JSONCopyFormatOptions result;
122
0
  result.context = context;
123
0
  result.geometry_format = ClientGeometryFormat(context);
124
0
  return result;
125
0
}
126
127
struct JSONCopyToJSONFunctionData : public FunctionData {
128
public:
129
  JSONCopyToJSONFunctionData(StructNames const_struct_names_p, bool has_date_format_p, string date_format_string_p,
130
                             StrfTimeFormat date_format_p, bool has_timestamp_format_p,
131
                             string timestamp_format_string_p, StrfTimeFormat timestamp_format_p,
132
                             unique_ptr<Expression> timestamptz_format_expression_p,
133
                             unique_ptr<Expression> timestamptz_ns_format_expression_p)
134
0
      : const_struct_names(std::move(const_struct_names_p)), has_date_format(has_date_format_p),
135
0
        date_format_string(std::move(date_format_string_p)), date_format(std::move(date_format_p)),
136
0
        has_timestamp_format(has_timestamp_format_p), timestamp_format_string(std::move(timestamp_format_string_p)),
137
0
        timestamp_format(std::move(timestamp_format_p)),
138
0
        timestamptz_format_expression(std::move(timestamptz_format_expression_p)),
139
0
        timestamptz_ns_format_expression(std::move(timestamptz_ns_format_expression_p)) {
140
0
  }
141
142
0
  unique_ptr<FunctionData> Copy() const override {
143
0
    return make_uniq<JSONCopyToJSONFunctionData>(
144
0
        const_struct_names.Copy(), has_date_format, date_format_string, date_format, has_timestamp_format,
145
0
        timestamp_format_string, timestamp_format,
146
0
        timestamptz_format_expression ? timestamptz_format_expression->Copy() : nullptr,
147
0
        timestamptz_ns_format_expression ? timestamptz_ns_format_expression->Copy() : nullptr);
148
0
  }
149
150
0
  bool Equals(const FunctionData &other_p) const override {
151
0
    auto &other = other_p.Cast<JSONCopyToJSONFunctionData>();
152
0
    return has_date_format == other.has_date_format && has_timestamp_format == other.has_timestamp_format &&
153
0
           date_format_string == other.date_format_string &&
154
0
           timestamp_format_string == other.timestamp_format_string &&
155
0
           const_struct_names.Equals(other.const_struct_names);
156
0
  }
157
158
0
  JSONCopyFormatOptions GetFormatOptions(Context &context) {
159
0
    JSONCopyFormatOptions result;
160
0
    result.geometry_format = ClientGeometryFormat(context);
161
0
    result.date_format = has_date_format ? optional_ptr<StrfTimeFormat>(&date_format) : nullptr;
162
0
    result.timestamp_format = has_timestamp_format ? optional_ptr<StrfTimeFormat>(&timestamp_format) : nullptr;
163
0
    result.context = context;
164
0
    result.timestamptz_format_expression = timestamptz_format_expression
165
0
                                               ? optional_ptr<const Expression>(timestamptz_format_expression.get())
166
0
                                               : nullptr;
167
0
    result.timestamptz_ns_format_expression =
168
0
        timestamptz_ns_format_expression ? optional_ptr<const Expression>(timestamptz_ns_format_expression.get())
169
0
                                         : nullptr;
170
0
    return result;
171
0
  }
172
173
public:
174
  StructNames const_struct_names;
175
  bool has_date_format;
176
  string date_format_string;
177
  StrfTimeFormat date_format;
178
  bool has_timestamp_format;
179
  string timestamp_format_string;
180
  StrfTimeFormat timestamp_format;
181
  unique_ptr<Expression> timestamptz_format_expression;
182
  unique_ptr<Expression> timestamptz_ns_format_expression;
183
};
184
185
//! Bind data for the GeoJSON Feature writer: which payload child is the geometry, which are properties, plus the
186
//! regular date/timestamp formatting options used for the property values
187
struct JSONCopyToGeoJSONFunctionData : public FunctionData {
188
public:
189
  JSONCopyToGeoJSONFunctionData(unique_ptr<JSONCopyToJSONFunctionData> formats_p, optional_idx geometry_index_p,
190
                                optional_idx id_index_p, vector<idx_t> property_indices_p, bool write_bbox_p)
191
0
      : formats(std::move(formats_p)), geometry_index(geometry_index_p), id_index(id_index_p),
192
0
        property_indices(std::move(property_indices_p)), write_bbox(write_bbox_p) {
193
0
  }
194
195
0
  unique_ptr<FunctionData> Copy() const override {
196
0
    auto formats_copy = unique_ptr_cast<FunctionData, JSONCopyToJSONFunctionData>(formats->Copy());
197
0
    return make_uniq<JSONCopyToGeoJSONFunctionData>(std::move(formats_copy), geometry_index, id_index,
198
0
                                                    property_indices, write_bbox);
199
0
  }
200
201
0
  bool Equals(const FunctionData &other_p) const override {
202
0
    auto &other = other_p.Cast<JSONCopyToGeoJSONFunctionData>();
203
0
    return geometry_index == other.geometry_index && id_index == other.id_index &&
204
0
           property_indices == other.property_indices && write_bbox == other.write_bbox &&
205
0
           formats->Equals(*other.formats);
206
0
  }
207
208
public:
209
  unique_ptr<JSONCopyToJSONFunctionData> formats;
210
  //! Invalid when there is no geometry column, i.e. every Feature gets a null geometry
211
  optional_idx geometry_index;
212
  //! Invalid when no column is written as the Feature-level "id"
213
  optional_idx id_index;
214
  vector<idx_t> property_indices;
215
  //! Whether to generate a "bbox" member from the geometry
216
  bool write_bbox;
217
};
218
219
0
static LogicalType GetJSONType(StructNames &const_struct_names, const LogicalType &type) {
220
0
  if (type.IsJSONType()) {
221
0
    return type;
222
0
  }
223
224
0
  switch (type.id()) {
225
  // These types can go directly into JSON
226
0
  case LogicalTypeId::SQLNULL:
227
0
  case LogicalTypeId::BOOLEAN:
228
0
  case LogicalTypeId::TINYINT:
229
0
  case LogicalTypeId::SMALLINT:
230
0
  case LogicalTypeId::INTEGER:
231
0
  case LogicalTypeId::BIGINT:
232
0
  case LogicalTypeId::HUGEINT:
233
0
  case LogicalTypeId::UHUGEINT:
234
0
  case LogicalTypeId::UTINYINT:
235
0
  case LogicalTypeId::USMALLINT:
236
0
  case LogicalTypeId::UINTEGER:
237
0
  case LogicalTypeId::UBIGINT:
238
0
  case LogicalTypeId::FLOAT:
239
0
  case LogicalTypeId::DOUBLE:
240
0
  case LogicalTypeId::BIT:
241
0
  case LogicalTypeId::BLOB:
242
0
  case LogicalTypeId::VARCHAR:
243
0
  case LogicalTypeId::ENUM:
244
0
  case LogicalTypeId::DATE:
245
0
  case LogicalTypeId::INTERVAL:
246
0
  case LogicalTypeId::TIME:
247
0
  case LogicalTypeId::TIME_TZ:
248
0
  case LogicalTypeId::TIMESTAMP:
249
0
  case LogicalTypeId::TIMESTAMP_TZ:
250
0
  case LogicalTypeId::TIMESTAMP_TZ_NS:
251
0
  case LogicalTypeId::TIMESTAMP_NS:
252
0
  case LogicalTypeId::TIMESTAMP_MS:
253
0
  case LogicalTypeId::TIMESTAMP_SEC:
254
0
  case LogicalTypeId::UUID:
255
0
  case LogicalTypeId::BIGNUM:
256
0
  case LogicalTypeId::DECIMAL:
257
  // GEOMETRY is emitted as either WKT or GeoJSON, so it must reach CreateValues untouched
258
0
  case LogicalTypeId::GEOMETRY:
259
0
    return type;
260
0
  case LogicalTypeId::VARIANT:
261
0
    return LogicalType::JSON();
262
0
  case LogicalTypeId::LIST:
263
0
    return LogicalType::LIST(GetJSONType(const_struct_names, ListType::GetChildType(type)));
264
0
  case LogicalTypeId::ARRAY:
265
0
    return LogicalType::ARRAY(GetJSONType(const_struct_names, ArrayType::GetChildType(type)),
266
0
                              ArrayType::GetSize(type));
267
  // Struct and MAP are treated as JSON values
268
0
  case LogicalTypeId::STRUCT: {
269
0
    child_list_t<LogicalType> child_types;
270
0
    for (const auto &child_type : StructType::GetChildTypes(type)) {
271
0
      const_struct_names.Insert(child_type.first.GetIdentifierName());
272
0
      child_types.emplace_back(child_type.first, GetJSONType(const_struct_names, child_type.second));
273
0
    }
274
0
    return LogicalType::STRUCT(child_types);
275
0
  }
276
  // A TUPLE is an unnamed struct: it is serialized as a JSON array (matching how Python serializes tuples)
277
0
  case LogicalTypeId::TUPLE: {
278
0
    vector<LogicalType> child_types;
279
0
    for (const auto &child_type : StructType::GetChildTypes(type)) {
280
0
      child_types.push_back(GetJSONType(const_struct_names, child_type.second));
281
0
    }
282
0
    return LogicalType::TUPLE(std::move(child_types));
283
0
  }
284
0
  case LogicalTypeId::MAP: {
285
0
    return LogicalType::MAP(MapType::KeyType(type), GetJSONType(const_struct_names, MapType::ValueType(type)));
286
0
  }
287
0
  case LogicalTypeId::UNION: {
288
0
    child_list_t<LogicalType> member_types;
289
0
    for (idx_t member_idx = 0; member_idx < UnionType::GetMemberCount(type); member_idx++) {
290
0
      auto &member_name = UnionType::GetMemberName(type, member_idx);
291
0
      auto &member_type = UnionType::GetMemberType(type, member_idx);
292
0
      const_struct_names.Insert(member_name.GetIdentifierName());
293
0
      member_types.emplace_back(member_name, GetJSONType(const_struct_names, member_type));
294
0
    }
295
0
    return LogicalType::UNION(member_types);
296
0
  }
297
  // All other types (e.g. date) are cast to VARCHAR
298
0
  default:
299
0
    return LogicalTypeId::VARCHAR;
300
0
  }
301
0
}
302
303
//! Resolves the argument types and the struct names - this is called from both resolve_types and bind, which only
304
//! works because the JSON type of a JSON type is the same type
305
static unique_ptr<FunctionData> JSONCreateBindParams(BoundScalarFunction &bound_function,
306
0
                                                     const vector<unique_ptr<Expression>> &arguments, bool object) {
307
0
  StructNames const_struct_names;
308
0
  auto &bound_arguments = bound_function.GetArguments();
309
0
  bound_arguments.clear();
310
0
  bound_arguments.reserve(arguments.size());
311
0
  for (idx_t i = 0; i < arguments.size(); i++) {
312
0
    auto &type = arguments[i]->GetReturnType();
313
0
    if (arguments[i]->HasParameter()) {
314
0
      throw ParameterNotResolvedException();
315
0
    } else if (object && i % 2 == 0) {
316
0
      if (type != LogicalType::VARCHAR) {
317
0
        throw BinderException("json_object() keys must be VARCHAR, add an explicit cast to argument %s",
318
0
                              arguments[i]->GetName());
319
0
      }
320
0
      bound_arguments.push_back(LogicalType::VARCHAR);
321
0
    } else {
322
      // Value, cast to types that we can put in JSON
323
0
      bound_arguments.push_back(GetJSONType(const_struct_names, type));
324
0
    }
325
0
  }
326
0
  return make_uniq<JSONCreateFunctionData>(std::move(const_struct_names));
327
0
}
328
329
template <class INPUT>
330
0
static unique_ptr<FunctionData> JSONObjectBind(INPUT &input) {
331
0
  auto &bound_function = input.GetBoundFunction();
332
0
  auto &arguments = input.GetArguments();
333
0
  if (arguments.size() % 2 != 0) {
334
0
    throw BinderException("json_object() requires an even number of arguments");
335
0
  }
336
0
  return JSONCreateBindParams(bound_function, arguments, true);
337
0
}
Unexecuted instantiation: json_create.cpp:duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::JSONObjectBind<duckdb::BindScalarFunctionInput>(duckdb::BindScalarFunctionInput&)
Unexecuted instantiation: json_create.cpp:duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::JSONObjectBind<duckdb::ResolveScalarFunctionTypesInput>(duckdb::ResolveScalarFunctionTypesInput&)
338
339
template <class INPUT>
340
0
static unique_ptr<FunctionData> JSONArrayBind(INPUT &input) {
341
0
  auto &bound_function = input.GetBoundFunction();
342
0
  auto &arguments = input.GetArguments();
343
0
  return JSONCreateBindParams(bound_function, arguments, false);
344
0
}
Unexecuted instantiation: json_create.cpp:duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::JSONArrayBind<duckdb::BindScalarFunctionInput>(duckdb::BindScalarFunctionInput&)
Unexecuted instantiation: json_create.cpp:duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::JSONArrayBind<duckdb::ResolveScalarFunctionTypesInput>(duckdb::ResolveScalarFunctionTypesInput&)
345
346
template <class INPUT>
347
0
static unique_ptr<FunctionData> ToJSONBind(INPUT &input) {
348
0
  auto &bound_function = input.GetBoundFunction();
349
0
  auto &arguments = input.GetArguments();
350
0
  if (arguments.size() != 1) {
351
0
    throw BinderException("to_json() takes exactly one argument");
352
0
  }
353
0
  return JSONCreateBindParams(bound_function, arguments, false);
354
0
}
Unexecuted instantiation: json_create.cpp:duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::ToJSONBind<duckdb::BindScalarFunctionInput>(duckdb::BindScalarFunctionInput&)
Unexecuted instantiation: json_create.cpp:duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::ToJSONBind<duckdb::ResolveScalarFunctionTypesInput>(duckdb::ResolveScalarFunctionTypesInput&)
355
356
template <class INPUT>
357
0
static unique_ptr<FunctionData> ArrayToJSONBind(INPUT &input) {
358
0
  auto &bound_function = input.GetBoundFunction();
359
0
  auto &arguments = input.GetArguments();
360
0
  if (arguments.size() != 1) {
361
0
    throw BinderException("array_to_json() takes exactly one argument");
362
0
  }
363
0
  auto arg_id = arguments[0]->GetReturnType().id();
364
0
  if (arguments[0]->HasParameter()) {
365
0
    throw ParameterNotResolvedException();
366
0
  }
367
0
  if (arg_id != LogicalTypeId::LIST && arg_id != LogicalTypeId::ARRAY && arg_id != LogicalTypeId::SQLNULL) {
368
0
    throw BinderException("array_to_json() argument type must be LIST or ARRAY");
369
0
  }
370
0
  return JSONCreateBindParams(bound_function, arguments, false);
371
0
}
Unexecuted instantiation: json_create.cpp:duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::ArrayToJSONBind<duckdb::BindScalarFunctionInput>(duckdb::BindScalarFunctionInput&)
Unexecuted instantiation: json_create.cpp:duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::ArrayToJSONBind<duckdb::ResolveScalarFunctionTypesInput>(duckdb::ResolveScalarFunctionTypesInput&)
372
373
template <class INPUT>
374
0
static unique_ptr<FunctionData> RowToJSONBind(INPUT &input) {
375
0
  auto &bound_function = input.GetBoundFunction();
376
0
  auto &arguments = input.GetArguments();
377
0
  if (arguments.size() != 1) {
378
0
    throw BinderException("row_to_json() takes exactly one argument");
379
0
  }
380
0
  auto arg_id = arguments[0]->GetReturnType().id();
381
0
  if (arguments[0]->HasParameter()) {
382
0
    throw ParameterNotResolvedException();
383
0
  }
384
0
  if (arguments[0]->GetReturnType().id() != LogicalTypeId::STRUCT && arg_id != LogicalTypeId::SQLNULL) {
385
0
    throw BinderException("row_to_json() argument type must be STRUCT");
386
0
  }
387
0
  return JSONCreateBindParams(bound_function, arguments, false);
388
0
}
Unexecuted instantiation: json_create.cpp:duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::RowToJSONBind<duckdb::BindScalarFunctionInput>(duckdb::BindScalarFunctionInput&)
Unexecuted instantiation: json_create.cpp:duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::RowToJSONBind<duckdb::ResolveScalarFunctionTypesInput>(duckdb::ResolveScalarFunctionTypesInput&)
389
390
template <unique_ptr<FunctionData> (*BIND)(ResolveScalarFunctionTypesInput &)>
391
0
static void JSONCreateResolveTypes(ResolveScalarFunctionTypesInput &input) {
392
0
  BIND(input);
393
0
}
Unexecuted instantiation: json_create.cpp:void duckdb::JSONCreateResolveTypes<&(duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::JSONObjectBind<duckdb::ResolveScalarFunctionTypesInput>(duckdb::ResolveScalarFunctionTypesInput&))>(duckdb::ResolveScalarFunctionTypesInput&)
Unexecuted instantiation: json_create.cpp:void duckdb::JSONCreateResolveTypes<&(duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::JSONArrayBind<duckdb::ResolveScalarFunctionTypesInput>(duckdb::ResolveScalarFunctionTypesInput&))>(duckdb::ResolveScalarFunctionTypesInput&)
Unexecuted instantiation: json_create.cpp:void duckdb::JSONCreateResolveTypes<&(duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::ToJSONBind<duckdb::ResolveScalarFunctionTypesInput>(duckdb::ResolveScalarFunctionTypesInput&))>(duckdb::ResolveScalarFunctionTypesInput&)
Unexecuted instantiation: json_create.cpp:void duckdb::JSONCreateResolveTypes<&(duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::JSONCopyToGeoJSONBind<duckdb::ResolveScalarFunctionTypesInput>(duckdb::ResolveScalarFunctionTypesInput&))>(duckdb::ResolveScalarFunctionTypesInput&)
Unexecuted instantiation: json_create.cpp:void duckdb::JSONCreateResolveTypes<&(duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::ArrayToJSONBind<duckdb::ResolveScalarFunctionTypesInput>(duckdb::ResolveScalarFunctionTypesInput&))>(duckdb::ResolveScalarFunctionTypesInput&)
Unexecuted instantiation: json_create.cpp:void duckdb::JSONCreateResolveTypes<&(duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::RowToJSONBind<duckdb::ResolveScalarFunctionTypesInput>(duckdb::ResolveScalarFunctionTypesInput&))>(duckdb::ResolveScalarFunctionTypesInput&)
394
395
static bool BindJSONCopyFormat(ClientContext &context, Expression &argument, const string &name, string &format_string,
396
0
                               StrfTimeFormat &format) {
397
0
  if (argument.HasParameter()) {
398
0
    throw ParameterNotResolvedException();
399
0
  }
400
0
  if (!argument.IsFoldable()) {
401
0
    throw InvalidInputException(argument, "json_copy_to_json %s format must be a constant", name);
402
0
  }
403
0
  auto value = ExpressionExecutor::EvaluateScalar(context, argument);
404
0
  if (value.IsNull()) {
405
0
    return false;
406
0
  }
407
0
  if (value.type().id() != LogicalTypeId::VARCHAR) {
408
0
    throw BinderException("json_copy_to_json %s format must be VARCHAR or NULL", name);
409
0
  }
410
0
  format_string = StringValue::Get(value);
411
0
  auto error = StrTimeFormat::ParseFormatSpecifier(format_string, format);
412
0
  if (!error.empty()) {
413
0
    throw InvalidInputException(argument, "Failed to parse format specifier %s: %s", format_string, error);
414
0
  }
415
0
  return true;
416
0
}
417
418
0
static void ParseJSONCopyFormatString(const string &format_string, const string &name, StrfTimeFormat &format) {
419
0
  auto error = StrTimeFormat::ParseFormatSpecifier(format_string, format);
420
0
  if (!error.empty()) {
421
0
    throw InvalidInputException("Failed to parse %s format specifier %s: %s", name, format_string, error);
422
0
  }
423
0
}
424
425
static unique_ptr<Expression> BindJSONCopyTimestampTZFormatter(ClientContext &context, const string &format_string,
426
0
                                                               const LogicalType &type) {
427
0
  vector<unique_ptr<Expression>> children;
428
0
  children.push_back(make_uniq<BoundReferenceExpression>(type, 0));
429
0
  children.push_back(make_uniq<BoundConstantExpression>(Value(format_string)));
430
431
0
  FunctionBinder function_binder(context);
432
0
  return function_binder.BindScalarFunction(Identifier::DefaultSchema(), "strftime", std::move(children));
433
0
}
434
435
static unique_ptr<JSONCopyToJSONFunctionData>
436
CreateJSONCopyToJSONFunctionData(ClientContext &context, StructNames const_struct_names, bool has_date_format,
437
0
                                 string date_format_string, bool has_timestamp_format, string timestamp_format_string) {
438
0
  StrfTimeFormat date_format;
439
0
  StrfTimeFormat timestamp_format;
440
0
  if (has_date_format) {
441
0
    ParseJSONCopyFormatString(date_format_string, "date", date_format);
442
0
  }
443
0
  if (has_timestamp_format) {
444
0
    ParseJSONCopyFormatString(timestamp_format_string, "timestamp", timestamp_format);
445
0
  }
446
447
0
  unique_ptr<Expression> timestamptz_format_expression;
448
0
  unique_ptr<Expression> timestamptz_ns_format_expression;
449
0
  if (has_timestamp_format) {
450
0
    timestamptz_format_expression =
451
0
        BindJSONCopyTimestampTZFormatter(context, timestamp_format_string, LogicalType::TIMESTAMP_TZ);
452
0
    timestamptz_ns_format_expression =
453
0
        BindJSONCopyTimestampTZFormatter(context, timestamp_format_string, LogicalType::TIMESTAMP_TZ_NS);
454
0
  }
455
456
0
  return make_uniq<JSONCopyToJSONFunctionData>(
457
0
      std::move(const_struct_names), has_date_format, std::move(date_format_string), std::move(date_format),
458
0
      has_timestamp_format, std::move(timestamp_format_string), std::move(timestamp_format),
459
0
      std::move(timestamptz_format_expression), std::move(timestamptz_ns_format_expression));
460
0
}
461
462
static unique_ptr<JSONCopyToJSONFunctionData> CreateJSONCopyToJSONFunctionData(ClientContext &context,
463
                                                                               StructNames const_struct_names,
464
                                                                               Expression &date_argument,
465
0
                                                                               Expression &timestamp_argument) {
466
0
  StrfTimeFormat date_format;
467
0
  StrfTimeFormat timestamp_format;
468
0
  string date_format_string;
469
0
  string timestamp_format_string;
470
0
  auto has_date_format = BindJSONCopyFormat(context, date_argument, "date", date_format_string, date_format);
471
0
  auto has_timestamp_format =
472
0
      BindJSONCopyFormat(context, timestamp_argument, "timestamp", timestamp_format_string, timestamp_format);
473
0
  return CreateJSONCopyToJSONFunctionData(context, std::move(const_struct_names), has_date_format,
474
0
                                          std::move(date_format_string), has_timestamp_format,
475
0
                                          std::move(timestamp_format_string));
476
0
}
477
478
0
static unique_ptr<FunctionData> JSONCopyToJSONBind(BindScalarFunctionInput &) {
479
0
  throw BinderException("%s is for internal use only", JSON_COPY_TO_JSON_INTERNAL_NAME);
480
0
}
481
482
template <class INPUT_TYPE, class RESULT_TYPE>
483
struct CreateJSONValue {
484
  static inline RESULT_TYPE Operation(const INPUT_TYPE &input) {
485
    throw NotImplementedException("Unsupported type for CreateJSONValue");
486
  }
487
};
488
489
template <class INPUT_TYPE>
490
struct CreateJSONValue<INPUT_TYPE, bool> {
491
0
  static inline yyjson_mut_val *Operation(yyjson_mut_doc *doc, const INPUT_TYPE &input) {
492
0
    return yyjson_mut_bool(doc, input);
493
0
  }
494
};
495
496
template <class INPUT_TYPE>
497
struct CreateJSONValue<INPUT_TYPE, uint64_t> {
498
0
  static inline yyjson_mut_val *Operation(yyjson_mut_doc *doc, const INPUT_TYPE &input) {
499
0
    return yyjson_mut_uint(doc, input);
500
0
  }
Unexecuted instantiation: duckdb::CreateJSONValue<unsigned char, unsigned long>::Operation(duckdb_yyjson::yyjson_mut_doc*, unsigned char const&)
Unexecuted instantiation: duckdb::CreateJSONValue<unsigned short, unsigned long>::Operation(duckdb_yyjson::yyjson_mut_doc*, unsigned short const&)
Unexecuted instantiation: duckdb::CreateJSONValue<unsigned int, unsigned long>::Operation(duckdb_yyjson::yyjson_mut_doc*, unsigned int const&)
Unexecuted instantiation: duckdb::CreateJSONValue<unsigned long, unsigned long>::Operation(duckdb_yyjson::yyjson_mut_doc*, unsigned long const&)
501
};
502
503
template <class INPUT_TYPE>
504
struct CreateJSONValue<INPUT_TYPE, int64_t> {
505
0
  static inline yyjson_mut_val *Operation(yyjson_mut_doc *doc, const INPUT_TYPE &input) {
506
0
    return yyjson_mut_sint(doc, input);
507
0
  }
Unexecuted instantiation: duckdb::CreateJSONValue<signed char, long>::Operation(duckdb_yyjson::yyjson_mut_doc*, signed char const&)
Unexecuted instantiation: duckdb::CreateJSONValue<short, long>::Operation(duckdb_yyjson::yyjson_mut_doc*, short const&)
Unexecuted instantiation: duckdb::CreateJSONValue<int, long>::Operation(duckdb_yyjson::yyjson_mut_doc*, int const&)
Unexecuted instantiation: duckdb::CreateJSONValue<long, long>::Operation(duckdb_yyjson::yyjson_mut_doc*, long const&)
508
};
509
510
template <class INPUT_TYPE>
511
struct CreateJSONValue<INPUT_TYPE, double> {
512
0
  static inline yyjson_mut_val *Operation(yyjson_mut_doc *doc, const INPUT_TYPE &input) {
513
0
    return yyjson_mut_real(doc, input);
514
0
  }
Unexecuted instantiation: duckdb::CreateJSONValue<float, double>::Operation(duckdb_yyjson::yyjson_mut_doc*, float const&)
Unexecuted instantiation: duckdb::CreateJSONValue<double, double>::Operation(duckdb_yyjson::yyjson_mut_doc*, double const&)
515
};
516
517
template <>
518
struct CreateJSONValue<string_t, string_t> {
519
0
  static inline yyjson_mut_val *Operation(yyjson_mut_doc *doc, const string_t &input) {
520
0
    return yyjson_mut_strncpy(doc, input.GetData(), input.GetSize());
521
0
  }
522
};
523
524
template <>
525
struct CreateJSONValue<hugeint_t, string_t> {
526
0
  static inline yyjson_mut_val *Operation(yyjson_mut_doc *doc, const hugeint_t &input) {
527
0
    const auto input_string = input.ToString();
528
0
    return yyjson_mut_rawncpy(doc, input_string.c_str(), input_string.length());
529
0
  }
530
};
531
532
template <>
533
struct CreateJSONValue<uhugeint_t, string_t> {
534
0
  static inline yyjson_mut_val *Operation(yyjson_mut_doc *doc, const uhugeint_t &input) {
535
0
    const auto input_string = input.ToString();
536
0
    return yyjson_mut_rawncpy(doc, input_string.c_str(), input_string.length());
537
0
  }
538
};
539
540
template <class T>
541
0
static inline yyjson_mut_val *CreateJSONValueFromJSON(yyjson_mut_doc *doc, const T &value) {
542
0
  return nullptr; // This function should only be called with string_t as template
543
0
}
Unexecuted instantiation: json_create.cpp:duckdb_yyjson::yyjson_mut_val* duckdb::CreateJSONValueFromJSON<bool>(duckdb_yyjson::yyjson_mut_doc*, bool const&)
Unexecuted instantiation: json_create.cpp:duckdb_yyjson::yyjson_mut_val* duckdb::CreateJSONValueFromJSON<signed char>(duckdb_yyjson::yyjson_mut_doc*, signed char const&)
Unexecuted instantiation: json_create.cpp:duckdb_yyjson::yyjson_mut_val* duckdb::CreateJSONValueFromJSON<short>(duckdb_yyjson::yyjson_mut_doc*, short const&)
Unexecuted instantiation: json_create.cpp:duckdb_yyjson::yyjson_mut_val* duckdb::CreateJSONValueFromJSON<int>(duckdb_yyjson::yyjson_mut_doc*, int const&)
Unexecuted instantiation: json_create.cpp:duckdb_yyjson::yyjson_mut_val* duckdb::CreateJSONValueFromJSON<long>(duckdb_yyjson::yyjson_mut_doc*, long const&)
Unexecuted instantiation: json_create.cpp:duckdb_yyjson::yyjson_mut_val* duckdb::CreateJSONValueFromJSON<duckdb::hugeint_t>(duckdb_yyjson::yyjson_mut_doc*, duckdb::hugeint_t const&)
Unexecuted instantiation: json_create.cpp:duckdb_yyjson::yyjson_mut_val* duckdb::CreateJSONValueFromJSON<duckdb::uhugeint_t>(duckdb_yyjson::yyjson_mut_doc*, duckdb::uhugeint_t const&)
Unexecuted instantiation: json_create.cpp:duckdb_yyjson::yyjson_mut_val* duckdb::CreateJSONValueFromJSON<unsigned char>(duckdb_yyjson::yyjson_mut_doc*, unsigned char const&)
Unexecuted instantiation: json_create.cpp:duckdb_yyjson::yyjson_mut_val* duckdb::CreateJSONValueFromJSON<unsigned short>(duckdb_yyjson::yyjson_mut_doc*, unsigned short const&)
Unexecuted instantiation: json_create.cpp:duckdb_yyjson::yyjson_mut_val* duckdb::CreateJSONValueFromJSON<unsigned int>(duckdb_yyjson::yyjson_mut_doc*, unsigned int const&)
Unexecuted instantiation: json_create.cpp:duckdb_yyjson::yyjson_mut_val* duckdb::CreateJSONValueFromJSON<unsigned long>(duckdb_yyjson::yyjson_mut_doc*, unsigned long const&)
Unexecuted instantiation: json_create.cpp:duckdb_yyjson::yyjson_mut_val* duckdb::CreateJSONValueFromJSON<float>(duckdb_yyjson::yyjson_mut_doc*, float const&)
Unexecuted instantiation: json_create.cpp:duckdb_yyjson::yyjson_mut_val* duckdb::CreateJSONValueFromJSON<double>(duckdb_yyjson::yyjson_mut_doc*, double const&)
544
545
template <>
546
0
inline yyjson_mut_val *CreateJSONValueFromJSON(yyjson_mut_doc *doc, const string_t &value) {
547
0
  auto value_doc = JSONCommon::ReadDocument(value, JSONCommon::READ_FLAG, &doc->alc);
548
0
  auto result = yyjson_val_mut_copy(doc, value_doc->root);
549
0
  return result;
550
0
}
551
552
// Forward declaration so we can recurse for nested types
553
static void CreateValues(const StructNames &names, yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v,
554
                         idx_t count, const JSONCopyFormatOptions &options = JSONCopyFormatOptions());
555
556
static void AddKeyValuePairs(yyjson_mut_doc *doc, yyjson_mut_val *objs[], const Vector &key_v, yyjson_mut_val *vals[],
557
0
                             idx_t count) {
558
0
  auto keys = key_v.Values<string_t>();
559
0
  for (idx_t i = 0; i < count; i++) {
560
0
    auto key_entry = keys[i];
561
0
    if (!key_entry.IsValid()) {
562
0
      throw InvalidInputException("JSON key cannot be NULL");
563
0
    }
564
0
    auto key = CreateJSONValue<string_t, string_t>::Operation(doc, key_entry.GetValue());
565
0
    yyjson_mut_obj_add(objs[i], key, vals[i]);
566
0
  }
567
0
}
568
569
static void CreateKeyValuePairs(const StructNames &names, yyjson_mut_doc *doc, yyjson_mut_val *objs[],
570
                                yyjson_mut_val *vals[], const Vector &key_v, Vector &value_v, idx_t count,
571
0
                                const JSONCopyFormatOptions &options = JSONCopyFormatOptions()) {
572
0
  CreateValues(names, doc, vals, value_v, count, options);
573
0
  AddKeyValuePairs(doc, objs, key_v, vals, count);
574
0
}
575
576
0
static void CreateValuesNull(yyjson_mut_doc *doc, yyjson_mut_val *vals[], idx_t count) {
577
0
  for (idx_t i = 0; i < count; i++) {
578
0
    vals[i] = yyjson_mut_null(doc);
579
0
  }
580
0
}
581
582
template <class INPUT_TYPE, class TARGET_TYPE>
583
0
static void TemplatedCreateValues(yyjson_mut_doc *doc, yyjson_mut_val *vals[], const Vector &value_v, idx_t count) {
584
0
  UnifiedVectorFormat value_data;
585
0
  value_v.ToUnifiedFormat(value_data);
586
0
  auto values = UnifiedVectorFormat::GetData<INPUT_TYPE>(value_data);
587
588
0
  const auto type_is_json = value_v.GetType().IsJSONType();
589
0
  for (idx_t i = 0; i < count; i++) {
590
0
    idx_t val_idx = value_data.sel->get_index(i);
591
0
    if (!value_data.validity.RowIsValid(val_idx)) {
592
0
      vals[i] = yyjson_mut_null(doc);
593
0
    } else if (type_is_json) {
594
0
      vals[i] = CreateJSONValueFromJSON(doc, values[val_idx]);
595
0
    } else {
596
0
      vals[i] = CreateJSONValue<INPUT_TYPE, TARGET_TYPE>::Operation(doc, values[val_idx]);
597
0
    }
598
0
    D_ASSERT(vals[i] != nullptr);
599
0
  }
600
0
}
Unexecuted instantiation: json_create.cpp:void duckdb::TemplatedCreateValues<bool, bool>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector const&, unsigned long)
Unexecuted instantiation: json_create.cpp:void duckdb::TemplatedCreateValues<signed char, long>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector const&, unsigned long)
Unexecuted instantiation: json_create.cpp:void duckdb::TemplatedCreateValues<short, long>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector const&, unsigned long)
Unexecuted instantiation: json_create.cpp:void duckdb::TemplatedCreateValues<int, long>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector const&, unsigned long)
Unexecuted instantiation: json_create.cpp:void duckdb::TemplatedCreateValues<long, long>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector const&, unsigned long)
Unexecuted instantiation: json_create.cpp:void duckdb::TemplatedCreateValues<duckdb::hugeint_t, duckdb::string_t>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector const&, unsigned long)
Unexecuted instantiation: json_create.cpp:void duckdb::TemplatedCreateValues<duckdb::uhugeint_t, duckdb::string_t>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector const&, unsigned long)
Unexecuted instantiation: json_create.cpp:void duckdb::TemplatedCreateValues<unsigned char, unsigned long>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector const&, unsigned long)
Unexecuted instantiation: json_create.cpp:void duckdb::TemplatedCreateValues<unsigned short, unsigned long>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector const&, unsigned long)
Unexecuted instantiation: json_create.cpp:void duckdb::TemplatedCreateValues<unsigned int, unsigned long>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector const&, unsigned long)
Unexecuted instantiation: json_create.cpp:void duckdb::TemplatedCreateValues<unsigned long, unsigned long>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector const&, unsigned long)
Unexecuted instantiation: json_create.cpp:void duckdb::TemplatedCreateValues<float, double>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector const&, unsigned long)
Unexecuted instantiation: json_create.cpp:void duckdb::TemplatedCreateValues<double, double>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector const&, unsigned long)
Unexecuted instantiation: json_create.cpp:void duckdb::TemplatedCreateValues<duckdb::string_t, duckdb::string_t>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector const&, unsigned long)
601
602
0
static void CreateRawValues(yyjson_mut_doc *doc, yyjson_mut_val *vals[], const Vector &value_v, idx_t count) {
603
0
  UnifiedVectorFormat value_data;
604
0
  value_v.ToUnifiedFormat(value_data);
605
0
  auto values = UnifiedVectorFormat::GetData<string_t>(value_data);
606
0
  for (idx_t i = 0; i < count; i++) {
607
0
    idx_t val_idx = value_data.sel->get_index(i);
608
0
    if (!value_data.validity.RowIsValid(val_idx)) {
609
0
      vals[i] = yyjson_mut_null(doc);
610
0
    } else {
611
0
      const auto &str = values[val_idx];
612
0
      vals[i] = yyjson_mut_rawncpy(doc, str.GetData(), str.GetSize());
613
0
    }
614
0
    D_ASSERT(vals[i] != nullptr);
615
0
  }
616
0
}
617
618
static void CreateValuesStruct(const StructNames &names, yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v,
619
0
                               idx_t count, const JSONCopyFormatOptions &options) {
620
  // Structs become values, therefore we initialize vals to JSON values
621
0
  for (idx_t i = 0; i < count; i++) {
622
0
    vals[i] = yyjson_mut_obj(doc);
623
0
  }
624
  // Initialize re-usable array for the nested values
625
0
  auto nested_vals = JSONCommon::AllocateArray<yyjson_mut_val *>(doc, count);
626
627
  // Add the key/value pairs to the values
628
0
  auto &entries = StructVector::GetEntries(value_v);
629
0
  for (idx_t entry_i = 0; entry_i < entries.size(); entry_i++) {
630
0
    Vector struct_key_v(Value(StructType::GetChildName(value_v.GetType(), entry_i).GetIdentifierName()),
631
0
                        count_t(count));
632
0
    auto &struct_val_v = entries[entry_i];
633
0
    CreateKeyValuePairs(names, doc, vals, nested_vals, struct_key_v, struct_val_v, count, options);
634
0
  }
635
  // Whole struct can be NULL
636
0
  UnifiedVectorFormat struct_data;
637
0
  value_v.ToUnifiedFormat(struct_data);
638
0
  for (idx_t i = 0; i < count; i++) {
639
0
    idx_t idx = struct_data.sel->get_index(i);
640
0
    if (!struct_data.validity.RowIsValid(idx)) {
641
0
      vals[i] = yyjson_mut_null(doc);
642
0
    }
643
0
  }
644
0
}
645
646
static void CreateValuesTuple(const StructNames &names, yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v,
647
0
                              idx_t count) {
648
  // a TUPLE becomes a JSON array (matching how Python serializes tuples)
649
0
  for (idx_t i = 0; i < count; i++) {
650
0
    vals[i] = yyjson_mut_arr(doc);
651
0
  }
652
0
  auto nested_vals = JSONCommon::AllocateArray<yyjson_mut_val *>(doc, count);
653
0
  auto &entries = StructVector::GetEntries(value_v);
654
0
  for (idx_t entry_i = 0; entry_i < entries.size(); entry_i++) {
655
0
    CreateValues(names, doc, nested_vals, entries[entry_i], count);
656
0
    for (idx_t i = 0; i < count; i++) {
657
0
      yyjson_mut_arr_append(vals[i], nested_vals[i]);
658
0
    }
659
0
  }
660
  // Whole tuple can be NULL
661
0
  UnifiedVectorFormat tuple_data;
662
0
  value_v.ToUnifiedFormat(tuple_data);
663
0
  for (idx_t i = 0; i < count; i++) {
664
0
    idx_t idx = tuple_data.sel->get_index(i);
665
0
    if (!tuple_data.validity.RowIsValid(idx)) {
666
0
      vals[i] = yyjson_mut_null(doc);
667
0
    }
668
0
  }
669
0
}
670
static void CreateValuesMapKeys(yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v, idx_t count,
671
                                const JSONCopyFormatOptions &options);
672
673
static void CreateValuesMap(const StructNames &names, yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v,
674
0
                            idx_t count, const JSONCopyFormatOptions &options) {
675
  // Create nested keys
676
0
  auto &map_key_v = MapVector::GetKeys(value_v);
677
0
  auto map_key_count = ListVector::GetListSize(value_v);
678
0
  auto nested_keys = JSONCommon::AllocateArray<yyjson_mut_val *>(doc, map_key_count);
679
0
  CreateValuesMapKeys(doc, nested_keys, map_key_v, map_key_count, options);
680
  // Create nested values
681
0
  auto &map_val_v = MapVector::GetValues(value_v);
682
0
  auto map_val_count = ListVector::GetListSize(value_v);
683
0
  auto nested_vals = JSONCommon::AllocateArray<yyjson_mut_val *>(doc, map_val_count);
684
0
  CreateValues(names, doc, nested_vals, map_val_v, map_val_count, options);
685
  // Add the key/value pairs to the values
686
0
  UnifiedVectorFormat map_data;
687
0
  value_v.ToUnifiedFormat(map_data);
688
0
  auto map_key_list_entries = UnifiedVectorFormat::GetData<list_entry_t>(map_data);
689
0
  for (idx_t i = 0; i < count; i++) {
690
0
    idx_t idx = map_data.sel->get_index(i);
691
0
    if (!map_data.validity.RowIsValid(idx)) {
692
      // Whole map can be NULL
693
0
      vals[i] = yyjson_mut_null(doc);
694
0
    } else {
695
0
      vals[i] = yyjson_mut_obj(doc);
696
0
      const auto &key_list_entry = map_key_list_entries[idx];
697
0
      for (idx_t child_i = key_list_entry.offset; child_i < key_list_entry.offset + key_list_entry.length;
698
0
           child_i++) {
699
0
        if (!unsafe_yyjson_is_null(nested_keys[child_i])) {
700
0
          yyjson_mut_obj_add(vals[i], nested_keys[child_i], nested_vals[child_i]);
701
0
        }
702
0
      }
703
0
    }
704
0
  }
705
0
}
706
707
static void CreateValuesUnion(const StructNames &names, yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v,
708
0
                              idx_t count, const JSONCopyFormatOptions &options) {
709
  // Structs become values, therefore we initialize vals to JSON values
710
0
  UnifiedVectorFormat value_data;
711
0
  value_v.ToUnifiedFormat(value_data);
712
0
  if (value_data.validity.CannotHaveNull()) {
713
0
    for (idx_t i = 0; i < count; i++) {
714
0
      vals[i] = yyjson_mut_obj(doc);
715
0
    }
716
0
  } else {
717
0
    for (idx_t i = 0; i < count; i++) {
718
0
      auto index = value_data.sel->get_index(i);
719
0
      if (!value_data.validity.RowIsValid(index)) {
720
        // Make the entry NULL if the Union value is NULL
721
0
        vals[i] = yyjson_mut_null(doc);
722
0
      } else {
723
0
        vals[i] = yyjson_mut_obj(doc);
724
0
      }
725
0
    }
726
0
  }
727
728
  // Initialize re-usable array for the nested values
729
0
  auto nested_vals = JSONCommon::AllocateArray<yyjson_mut_val *>(doc, count);
730
731
0
  auto &tag_v = UnionVector::GetTags(value_v);
732
0
  UnifiedVectorFormat tag_data;
733
0
  tag_v.ToUnifiedFormat(tag_data);
734
735
  // Add the key/value pairs to the values
736
0
  for (idx_t member_idx = 0; member_idx < UnionType::GetMemberCount(value_v.GetType()); member_idx++) {
737
0
    auto &member_val_v = UnionVector::GetMember(value_v, member_idx);
738
0
    Vector member_key_v(Value(UnionType::GetMemberName(value_v.GetType(), member_idx).GetIdentifierName()),
739
0
                        count_t(count));
740
741
    // This implementation is not optimal since we convert the entire member vector,
742
    // and then skip the rows not matching the tag afterwards.
743
744
0
    CreateValues(names, doc, nested_vals, member_val_v, count, options);
745
746
    // This is a inlined copy of AddKeyValuePairs but we also skip null tags
747
    // and the rows where the member is not matching the tag
748
0
    UnifiedVectorFormat key_data;
749
0
    member_key_v.ToUnifiedFormat(key_data);
750
0
    auto keys = UnifiedVectorFormat::GetData<string_t>(key_data);
751
752
0
    for (idx_t i = 0; i < count; i++) {
753
0
      auto value_index = value_data.sel->get_index(i);
754
0
      if (!value_data.validity.RowIsValid(value_index)) {
755
        // This entry is just NULL in it's entirety
756
0
        continue;
757
0
      }
758
0
      auto tag_idx = tag_data.sel->get_index(i);
759
0
      if (!tag_data.validity.RowIsValid(tag_idx)) {
760
0
        continue;
761
0
      }
762
0
      auto tag = (UnifiedVectorFormat::GetData<uint8_t>(tag_data))[tag_idx];
763
0
      if (tag != member_idx) {
764
0
        continue;
765
0
      }
766
0
      auto key_idx = key_data.sel->get_index(i);
767
0
      if (!key_data.validity.RowIsValid(key_idx)) {
768
0
        continue;
769
0
      }
770
0
      auto key = CreateJSONValue<string_t, string_t>::Operation(doc, keys[key_idx]);
771
0
      yyjson_mut_obj_add(vals[i], key, nested_vals[i]);
772
0
    }
773
0
  }
774
0
}
775
776
static void CreateValuesList(const StructNames &names, yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v,
777
0
                             idx_t count, const JSONCopyFormatOptions &options) {
778
  // Initialize array for the nested values
779
0
  auto &child_v = ListVector::GetChildMutable(value_v);
780
0
  auto child_count = ListVector::GetListSize(value_v);
781
0
  auto nested_vals = JSONCommon::AllocateArray<yyjson_mut_val *>(doc, child_count);
782
  // Fill nested_vals with list values
783
0
  CreateValues(names, doc, nested_vals, child_v, child_count, options);
784
  // Now we add the values to the appropriate JSON arrays
785
0
  UnifiedVectorFormat list_data;
786
0
  value_v.ToUnifiedFormat(list_data);
787
0
  auto list_entries = UnifiedVectorFormat::GetData<list_entry_t>(list_data);
788
0
  for (idx_t i = 0; i < count; i++) {
789
0
    idx_t idx = list_data.sel->get_index(i);
790
0
    if (!list_data.validity.RowIsValid(idx)) {
791
0
      vals[i] = yyjson_mut_null(doc);
792
0
    } else {
793
0
      vals[i] = yyjson_mut_arr(doc);
794
0
      const auto &entry = list_entries[idx];
795
0
      for (idx_t child_i = entry.offset; child_i < entry.offset + entry.length; child_i++) {
796
0
        yyjson_mut_arr_append(vals[i], nested_vals[child_i]);
797
0
      }
798
0
    }
799
0
  }
800
0
}
801
802
static void CreateValuesArray(const StructNames &names, yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v,
803
0
                              idx_t count, const JSONCopyFormatOptions &options) {
804
0
  value_v.Flatten();
805
806
  // Initialize array for the nested values
807
0
  auto &child_v = ArrayVector::GetChildMutable(value_v);
808
0
  auto array_size = ArrayType::GetSize(value_v.GetType());
809
0
  auto child_count = count * array_size;
810
811
0
  auto nested_vals = JSONCommon::AllocateArray<yyjson_mut_val *>(doc, child_count);
812
  // Fill nested_vals with list values
813
0
  CreateValues(names, doc, nested_vals, child_v, child_count, options);
814
  // Now we add the values to the appropriate JSON arrays
815
0
  UnifiedVectorFormat list_data;
816
0
  value_v.ToUnifiedFormat(list_data);
817
0
  for (idx_t i = 0; i < count; i++) {
818
0
    idx_t idx = list_data.sel->get_index(i);
819
0
    if (!list_data.validity.RowIsValid(idx)) {
820
0
      vals[i] = yyjson_mut_null(doc);
821
0
    } else {
822
0
      vals[i] = yyjson_mut_arr(doc);
823
0
      auto offset = idx * array_size;
824
0
      for (idx_t child_i = offset; child_i < offset + array_size; child_i++) {
825
0
        yyjson_mut_arr_append(vals[i], nested_vals[child_i]);
826
0
      }
827
0
    }
828
0
  }
829
0
}
830
831
0
static void CreateValuesFromDefaultCast(yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v, idx_t count) {
832
0
  Vector string_vector(LogicalTypeId::VARCHAR, count);
833
0
  VectorOperations::DefaultCast(value_v, string_vector, count);
834
0
  TemplatedCreateValues<string_t, string_t>(doc, vals, string_vector, count);
835
0
}
836
837
0
static void CreateValuesGeometry(yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v, idx_t count) {
838
0
  UnifiedVectorFormat value_data;
839
0
  value_v.ToUnifiedFormat(value_data);
840
0
  auto values = UnifiedVectorFormat::GetData<string_t>(value_data);
841
0
  for (idx_t i = 0; i < count; i++) {
842
0
    const auto idx = value_data.sel->get_index(i);
843
0
    if (!value_data.validity.RowIsValid(idx)) {
844
0
      vals[i] = yyjson_mut_null(doc);
845
0
    } else {
846
0
      vals[i] = JSONGeometry::ToGeoJSON(values[idx], doc);
847
0
    }
848
0
  }
849
0
}
850
851
template <class FILL>
852
static void CreateValuesFormatted(yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v, idx_t count,
853
0
                                  bool has_format, FILL &&fill_strings) {
854
0
  if (!has_format) {
855
0
    CreateValuesFromDefaultCast(doc, vals, value_v, count);
856
0
    return;
857
0
  }
858
0
  Vector string_vector(LogicalType::VARCHAR, count);
859
0
  fill_strings(string_vector);
860
0
  TemplatedCreateValues<string_t, string_t>(doc, vals, string_vector, count);
861
0
}
Unexecuted instantiation: json_create.cpp:void duckdb::CreateValuesFormatted<duckdb::CreateValuesDate(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector&, unsigned long, duckdb::JSONCopyFormatOptions const&)::$_0>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector&, unsigned long, bool, duckdb::CreateValuesDate(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector&, unsigned long, duckdb::JSONCopyFormatOptions const&)::$_0&&)
Unexecuted instantiation: json_create.cpp:void duckdb::CreateValuesFormatted<duckdb::CreateValuesTimestamp(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector&, unsigned long, duckdb::JSONCopyFormatOptions const&)::$_0>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector&, unsigned long, bool, duckdb::CreateValuesTimestamp(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector&, unsigned long, duckdb::JSONCopyFormatOptions const&)::$_0&&)
Unexecuted instantiation: json_create.cpp:void duckdb::CreateValuesFormatted<duckdb::CreateValuesTimestampNS(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector&, unsigned long, duckdb::JSONCopyFormatOptions const&)::$_0>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector&, unsigned long, bool, duckdb::CreateValuesTimestampNS(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector&, unsigned long, duckdb::JSONCopyFormatOptions const&)::$_0&&)
Unexecuted instantiation: json_create.cpp:void duckdb::CreateValuesFormatted<duckdb::CreateValuesTimestampTZ(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector&, unsigned long, duckdb::JSONCopyFormatOptions const&)::$_0>(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector&, unsigned long, bool, duckdb::CreateValuesTimestampTZ(duckdb_yyjson::yyjson_mut_doc*, duckdb_yyjson::yyjson_mut_val**, duckdb::Vector&, unsigned long, duckdb::JSONCopyFormatOptions const&)::$_0&&)
862
863
static void CreateValuesDate(yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v, idx_t count,
864
0
                             const JSONCopyFormatOptions &options) {
865
0
  CreateValuesFormatted(doc, vals, value_v, count, bool(options.date_format), [&](Vector &string_vector) {
866
0
    options.date_format->ConvertDateVector(value_v, string_vector);
867
0
  });
868
0
}
869
870
static void CreateValuesTimestamp(yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v, idx_t count,
871
0
                                  const JSONCopyFormatOptions &options) {
872
0
  if (options.timestamp_format && value_v.GetType().id() != LogicalTypeId::TIMESTAMP) {
873
0
    Vector timestamp_vector(LogicalType::TIMESTAMP, count);
874
0
    VectorOperations::DefaultCast(value_v, timestamp_vector, count);
875
0
    CreateValuesTimestamp(doc, vals, timestamp_vector, count, options);
876
0
    return;
877
0
  }
878
0
  CreateValuesFormatted(doc, vals, value_v, count, bool(options.timestamp_format), [&](Vector &string_vector) {
879
0
    options.timestamp_format->ConvertTimestampVector(value_v, string_vector);
880
0
  });
881
0
}
882
883
static void CreateValuesTimestampNS(yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v, idx_t count,
884
0
                                    const JSONCopyFormatOptions &options) {
885
0
  CreateValuesFormatted(doc, vals, value_v, count, bool(options.timestamp_format), [&](Vector &string_vector) {
886
0
    options.timestamp_format->ConvertTimestampNSVector(value_v, string_vector);
887
0
  });
888
0
}
889
890
static void CreateValuesTimestampTZ(yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v, idx_t count,
891
0
                                    const JSONCopyFormatOptions &options) {
892
0
  if (!options.timestamp_format) {
893
    // no COPY format was given - use the full cast set so that the session time zone is applied
894
0
    Vector string_vector(LogicalType::VARCHAR, count);
895
0
    if (options.context) {
896
0
      VectorOperations::Cast(*options.context, value_v, string_vector, count, true);
897
0
    } else {
898
0
      VectorOperations::DefaultCast(value_v, string_vector, count);
899
0
    }
900
0
    TemplatedCreateValues<string_t, string_t>(doc, vals, string_vector, count);
901
0
    return;
902
0
  }
903
0
  CreateValuesFormatted(doc, vals, value_v, count, true, [&](Vector &string_vector) {
904
0
    auto format_expression = value_v.GetType().id() == LogicalTypeId::TIMESTAMP_TZ_NS
905
0
                                 ? options.timestamptz_ns_format_expression
906
0
                                 : options.timestamptz_format_expression;
907
0
    if (!options.context || !format_expression) {
908
0
      throw InternalException("Missing bound TIMESTAMPTZ formatter for JSON COPY");
909
0
    }
910
0
    DataChunk input;
911
0
    input.InitializeEmpty({value_v.GetType()});
912
0
    input.data[0].Reference(value_v);
913
0
    input.CheckCardinality(count);
914
0
    ExpressionExecutor executor(*options.context, *format_expression);
915
0
    executor.ExecuteExpression(input, string_vector);
916
0
  });
917
0
}
918
919
static void CreateValuesMapKeys(yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v, idx_t count,
920
0
                                const JSONCopyFormatOptions &options) {
921
0
  switch (value_v.GetType().id()) {
922
0
  case LogicalTypeId::DATE:
923
0
    CreateValuesDate(doc, vals, value_v, count, options);
924
0
    break;
925
0
  case LogicalTypeId::TIMESTAMP:
926
0
  case LogicalTypeId::TIMESTAMP_MS:
927
0
  case LogicalTypeId::TIMESTAMP_SEC:
928
0
    CreateValuesTimestamp(doc, vals, value_v, count, options);
929
0
    break;
930
0
  case LogicalTypeId::TIMESTAMP_NS:
931
0
    CreateValuesTimestampNS(doc, vals, value_v, count, options);
932
0
    break;
933
0
  case LogicalTypeId::TIMESTAMP_TZ:
934
0
  case LogicalTypeId::TIMESTAMP_TZ_NS:
935
0
    CreateValuesTimestampTZ(doc, vals, value_v, count, options);
936
0
    break;
937
0
  default:
938
0
    CreateValuesFromDefaultCast(doc, vals, value_v, count);
939
0
    break;
940
0
  }
941
0
}
942
943
static void CreateValues(const StructNames &names, yyjson_mut_doc *doc, yyjson_mut_val *vals[], Vector &value_v,
944
0
                         idx_t count, const JSONCopyFormatOptions &options) {
945
0
  const auto &type = value_v.GetType();
946
0
  switch (type.id()) {
947
0
  case LogicalTypeId::SQLNULL:
948
0
    CreateValuesNull(doc, vals, count);
949
0
    break;
950
0
  case LogicalTypeId::BOOLEAN:
951
0
    TemplatedCreateValues<bool, bool>(doc, vals, value_v, count);
952
0
    break;
953
0
  case LogicalTypeId::TINYINT:
954
0
    TemplatedCreateValues<int8_t, int64_t>(doc, vals, value_v, count);
955
0
    break;
956
0
  case LogicalTypeId::SMALLINT:
957
0
    TemplatedCreateValues<int16_t, int64_t>(doc, vals, value_v, count);
958
0
    break;
959
0
  case LogicalTypeId::INTEGER:
960
0
    TemplatedCreateValues<int32_t, int64_t>(doc, vals, value_v, count);
961
0
    break;
962
0
  case LogicalTypeId::BIGINT:
963
0
    TemplatedCreateValues<int64_t, int64_t>(doc, vals, value_v, count);
964
0
    break;
965
0
  case LogicalTypeId::HUGEINT:
966
0
    TemplatedCreateValues<hugeint_t, string_t>(doc, vals, value_v, count);
967
0
    break;
968
0
  case LogicalTypeId::UHUGEINT:
969
0
    TemplatedCreateValues<uhugeint_t, string_t>(doc, vals, value_v, count);
970
0
    break;
971
0
  case LogicalTypeId::UTINYINT:
972
0
    TemplatedCreateValues<uint8_t, uint64_t>(doc, vals, value_v, count);
973
0
    break;
974
0
  case LogicalTypeId::USMALLINT:
975
0
    TemplatedCreateValues<uint16_t, uint64_t>(doc, vals, value_v, count);
976
0
    break;
977
0
  case LogicalTypeId::UINTEGER:
978
0
    TemplatedCreateValues<uint32_t, uint64_t>(doc, vals, value_v, count);
979
0
    break;
980
0
  case LogicalTypeId::UBIGINT:
981
0
    TemplatedCreateValues<uint64_t, uint64_t>(doc, vals, value_v, count);
982
0
    break;
983
0
  case LogicalTypeId::FLOAT:
984
0
    TemplatedCreateValues<float, double>(doc, vals, value_v, count);
985
0
    break;
986
0
  case LogicalTypeId::DOUBLE:
987
0
    TemplatedCreateValues<double, double>(doc, vals, value_v, count);
988
0
    break;
989
0
  case LogicalTypeId::VARCHAR:
990
0
    TemplatedCreateValues<string_t, string_t>(doc, vals, value_v, count);
991
0
    break;
992
0
  case LogicalTypeId::STRUCT:
993
0
    CreateValuesStruct(names, doc, vals, value_v, count, options);
994
0
    break;
995
0
  case LogicalTypeId::TUPLE:
996
0
    CreateValuesTuple(names, doc, vals, value_v, count);
997
0
    break;
998
0
  case LogicalTypeId::MAP:
999
0
    CreateValuesMap(names, doc, vals, value_v, count, options);
1000
0
    break;
1001
0
  case LogicalTypeId::LIST:
1002
0
    CreateValuesList(names, doc, vals, value_v, count, options);
1003
0
    break;
1004
0
  case LogicalTypeId::UNION:
1005
0
    CreateValuesUnion(names, doc, vals, value_v, count, options);
1006
0
    break;
1007
0
  case LogicalTypeId::ARRAY:
1008
0
    CreateValuesArray(names, doc, vals, value_v, count, options);
1009
0
    break;
1010
0
  case LogicalTypeId::DATE:
1011
0
    CreateValuesDate(doc, vals, value_v, count, options);
1012
0
    break;
1013
0
  case LogicalTypeId::TIMESTAMP:
1014
0
  case LogicalTypeId::TIMESTAMP_MS:
1015
0
  case LogicalTypeId::TIMESTAMP_SEC:
1016
0
    CreateValuesTimestamp(doc, vals, value_v, count, options);
1017
0
    break;
1018
0
  case LogicalTypeId::TIMESTAMP_NS:
1019
0
    CreateValuesTimestampNS(doc, vals, value_v, count, options);
1020
0
    break;
1021
0
  case LogicalTypeId::TIMESTAMP_TZ:
1022
0
  case LogicalTypeId::TIMESTAMP_TZ_NS:
1023
0
    CreateValuesTimestampTZ(doc, vals, value_v, count, options);
1024
0
    break;
1025
0
  case LogicalTypeId::BIT:
1026
0
  case LogicalTypeId::BLOB:
1027
0
  case LogicalTypeId::LEGACY_AGGREGATE_STATE:
1028
0
  case LogicalTypeId::ENUM:
1029
0
  case LogicalTypeId::INTERVAL:
1030
0
  case LogicalTypeId::TIME:
1031
0
  case LogicalTypeId::TIME_NS:
1032
0
  case LogicalTypeId::TIME_TZ:
1033
0
  case LogicalTypeId::UUID: {
1034
0
    CreateValuesFromDefaultCast(doc, vals, value_v, count);
1035
0
    break;
1036
0
  }
1037
0
  case LogicalTypeId::GEOMETRY: {
1038
0
    if (options.geometry_format == JSONGeometryFormat::GEOJSON) {
1039
0
      CreateValuesGeometry(doc, vals, value_v, count);
1040
0
    } else {
1041
0
      CreateValuesFromDefaultCast(doc, vals, value_v, count);
1042
0
    }
1043
0
    break;
1044
0
  }
1045
0
  case LogicalTypeId::BIGNUM: {
1046
0
    Vector string_vector(LogicalTypeId::VARCHAR, count);
1047
0
    VectorOperations::DefaultCast(value_v, string_vector, count);
1048
0
    CreateRawValues(doc, vals, string_vector, count);
1049
0
    break;
1050
0
  }
1051
0
  case LogicalTypeId::VARIANT: {
1052
0
    Vector json_vector(LogicalType::JSON(), count);
1053
0
    VectorOperations::DefaultCast(value_v, json_vector, count);
1054
0
    TemplatedCreateValues<string_t, string_t>(doc, vals, json_vector, count);
1055
0
    break;
1056
0
  }
1057
0
  case LogicalTypeId::DECIMAL: {
1058
0
    if (DecimalType::GetWidth(type) > 15) {
1059
0
      Vector string_vector(LogicalTypeId::VARCHAR, count);
1060
0
      VectorOperations::DefaultCast(value_v, string_vector, count);
1061
0
      CreateRawValues(doc, vals, string_vector, count);
1062
0
    } else {
1063
0
      Vector double_vector(LogicalType::DOUBLE, count);
1064
0
      VectorOperations::DefaultCast(value_v, double_vector, count);
1065
0
      TemplatedCreateValues<double, double>(doc, vals, double_vector, count);
1066
0
    }
1067
0
    break;
1068
0
  }
1069
0
  case LogicalTypeId::INVALID:
1070
0
  case LogicalTypeId::UNKNOWN:
1071
0
  case LogicalTypeId::ANY:
1072
0
  case LogicalTypeId::TEMPLATE:
1073
0
  case LogicalTypeId::UNBOUND:
1074
0
  case LogicalTypeId::TYPE:
1075
0
  case LogicalTypeId::CHAR:
1076
0
  case LogicalTypeId::STRING_LITERAL:
1077
0
  case LogicalTypeId::INTEGER_LITERAL:
1078
0
  case LogicalTypeId::POINTER:
1079
0
  case LogicalTypeId::VALIDITY:
1080
0
  case LogicalTypeId::TABLE:
1081
0
  case LogicalTypeId::LAMBDA:
1082
0
    throw InternalException("Unsupported type arrived at JSON create function");
1083
0
  }
1084
0
}
1085
1086
0
static void ObjectFunction(DataChunk &args, ExpressionState &state, Vector &result) {
1087
0
  auto &func_expr = state.expr.Cast<BoundFunctionExpression>();
1088
0
  const auto &info = func_expr.BindInfo()->Cast<JSONCreateFunctionData>();
1089
0
  auto &lstate = JSONFunctionLocalState::ResetAndGet(state);
1090
0
  auto alc = lstate.json_allocator->GetYYAlc();
1091
0
  auto options = ClientFormatOptions(state.GetContext());
1092
1093
  // Initialize values
1094
0
  const idx_t count = args.size();
1095
0
  auto doc = JSONCommon::CreateDocument(alc);
1096
0
  auto objs = JSONCommon::AllocateArray<yyjson_mut_val *>(doc, count);
1097
0
  for (idx_t i = 0; i < count; i++) {
1098
0
    objs[i] = yyjson_mut_obj(doc);
1099
0
  }
1100
  // Initialize a re-usable value array
1101
0
  auto vals = JSONCommon::AllocateArray<yyjson_mut_val *>(doc, count);
1102
  // Loop through key/value pairs
1103
0
  for (idx_t pair_idx = 0; pair_idx < args.data.size() / 2; pair_idx++) {
1104
0
    Vector &key_v = args.data[pair_idx * 2];
1105
0
    Vector &value_v = args.data[pair_idx * 2 + 1];
1106
0
    CreateKeyValuePairs(info.const_struct_names, doc, objs, vals, key_v, value_v, count, options);
1107
0
  }
1108
  // Write JSON values to string
1109
0
  auto objects = FlatVector::GetDataMutable<string_t>(result);
1110
0
  for (idx_t i = 0; i < count; i++) {
1111
0
    objects[i] = JSONCommon::WriteVal<yyjson_mut_val>(objs[i], alc);
1112
0
  }
1113
0
  JSONAllocator::AddBuffer(result, alc);
1114
0
}
1115
1116
0
static void ArrayFunction(DataChunk &args, ExpressionState &state, Vector &result) {
1117
0
  auto &func_expr = state.expr.Cast<BoundFunctionExpression>();
1118
0
  const auto &info = func_expr.BindInfo()->Cast<JSONCreateFunctionData>();
1119
0
  auto &lstate = JSONFunctionLocalState::ResetAndGet(state);
1120
0
  auto alc = lstate.json_allocator->GetYYAlc();
1121
0
  auto options = ClientFormatOptions(state.GetContext());
1122
1123
  // Initialize arrays
1124
0
  const idx_t count = args.size();
1125
0
  auto doc = JSONCommon::CreateDocument(alc);
1126
0
  auto arrs = JSONCommon::AllocateArray<yyjson_mut_val *>(doc, count);
1127
0
  for (idx_t i = 0; i < count; i++) {
1128
0
    arrs[i] = yyjson_mut_arr(doc);
1129
0
  }
1130
  // Initialize a re-usable value array
1131
0
  auto vals = JSONCommon::AllocateArray<yyjson_mut_val *>(doc, count);
1132
  // Loop through args
1133
0
  for (auto &v : args.data) {
1134
0
    CreateValues(info.const_struct_names, doc, vals, v, count, options);
1135
0
    for (idx_t i = 0; i < count; i++) {
1136
0
      yyjson_mut_arr_append(arrs[i], vals[i]);
1137
0
    }
1138
0
  }
1139
  // Write JSON arrays to string
1140
0
  auto objects = FlatVector::GetDataMutable<string_t>(result);
1141
0
  for (idx_t i = 0; i < count; i++) {
1142
0
    objects[i] = JSONCommon::WriteVal<yyjson_mut_val>(arrs[i], alc);
1143
0
  }
1144
0
  JSONAllocator::AddBuffer(result, alc);
1145
0
}
1146
1147
static void ToJSONFunctionInternal(const StructNames &names, Vector &input, const idx_t count, Vector &result,
1148
0
                                   yyjson_alc *alc, const JSONCopyFormatOptions &options = JSONCopyFormatOptions()) {
1149
  // Initialize array for values
1150
0
  auto doc = JSONCommon::CreateDocument(alc);
1151
0
  auto vals = JSONCommon::AllocateArray<yyjson_mut_val *>(doc, count);
1152
0
  CreateValues(names, doc, vals, input, count, options);
1153
1154
  // Write JSON values to string
1155
0
  auto objects = FlatVector::GetDataMutable<string_t>(result);
1156
0
  auto &result_validity = FlatVector::ValidityMutable(result);
1157
0
  UnifiedVectorFormat input_data;
1158
0
  input.ToUnifiedFormat(input_data);
1159
0
  for (idx_t i = 0; i < count; i++) {
1160
0
    idx_t idx = input_data.sel->get_index(i);
1161
0
    if (input_data.validity.RowIsValid(idx)) {
1162
0
      objects[i] = JSONCommon::WriteVal<yyjson_mut_val>(vals[i], alc);
1163
0
    } else {
1164
0
      result_validity.SetInvalid(i);
1165
0
    }
1166
0
  }
1167
1168
0
  if (input.GetVectorType() == VectorType::CONSTANT_VECTOR || count == 1) {
1169
0
    result.SetVectorType(VectorType::CONSTANT_VECTOR);
1170
0
  }
1171
1172
0
  JSONAllocator::AddBuffer(result, alc);
1173
0
}
1174
1175
0
static void ToJSONFunction(DataChunk &args, ExpressionState &state, Vector &result) {
1176
0
  auto &func_expr = state.expr.Cast<BoundFunctionExpression>();
1177
0
  const auto &info = func_expr.BindInfo()->Cast<JSONCreateFunctionData>();
1178
0
  auto &lstate = JSONFunctionLocalState::ResetAndGet(state);
1179
0
  auto alc = lstate.json_allocator->GetYYAlc();
1180
0
  auto options = ClientFormatOptions(state.GetContext());
1181
1182
0
  ToJSONFunctionInternal(info.const_struct_names, args.data[0], args.size(), result, alc, options);
1183
0
}
1184
1185
0
static void JSONCopyToJSONFunction(DataChunk &args, ExpressionState &state, Vector &result) {
1186
0
  auto &func_expr = state.expr.Cast<BoundFunctionExpression>();
1187
0
  auto &info = func_expr.BindInfo()->Cast<JSONCopyToJSONFunctionData>();
1188
0
  auto &lstate = JSONFunctionLocalState::ResetAndGet(state);
1189
0
  auto alc = lstate.json_allocator->GetYYAlc();
1190
0
  auto options = info.GetFormatOptions(state.GetContext());
1191
1192
0
  ToJSONFunctionInternal(info.const_struct_names, args.data[0], args.size(), result, alc, options);
1193
0
}
1194
1195
//===--------------------------------------------------------------------===//
1196
// COPY ... TO ... (FORMAT GEOJSON)
1197
//===--------------------------------------------------------------------===//
1198
//! Generate a "bbox" from each geometry. GeoJSON orders it as all the minimums followed by all the maximums, and
1199
//! includes Z when the geometry has it. Geometries without a finite extent (NULL or empty) get no bbox at all.
1200
static void AddGeoJSONBoundingBoxes(yyjson_mut_doc *doc, yyjson_mut_val *features[], Vector &geometry_v,
1201
0
                                    const idx_t count) {
1202
0
  UnifiedVectorFormat geometry_data;
1203
0
  geometry_v.ToUnifiedFormat(geometry_data);
1204
0
  auto geometries = UnifiedVectorFormat::GetData<string_t>(geometry_data);
1205
0
  for (idx_t i = 0; i < count; i++) {
1206
0
    const auto idx = geometry_data.sel->get_index(i);
1207
0
    if (!geometry_data.validity.RowIsValid(idx)) {
1208
0
      continue;
1209
0
    }
1210
0
    auto extent = GeometryExtent::Empty();
1211
0
    Geometry::GetExtent(geometries[idx], extent);
1212
0
    if (!extent.HasXY()) {
1213
0
      continue;
1214
0
    }
1215
0
    auto bbox = yyjson_mut_arr(doc);
1216
0
    const auto has_z = extent.HasZ();
1217
0
    yyjson_mut_arr_add_real(doc, bbox, extent.x_min);
1218
0
    yyjson_mut_arr_add_real(doc, bbox, extent.y_min);
1219
0
    if (has_z) {
1220
0
      yyjson_mut_arr_add_real(doc, bbox, extent.z_min);
1221
0
    }
1222
0
    yyjson_mut_arr_add_real(doc, bbox, extent.x_max);
1223
0
    yyjson_mut_arr_add_real(doc, bbox, extent.y_max);
1224
0
    if (has_z) {
1225
0
      yyjson_mut_arr_add_real(doc, bbox, extent.z_max);
1226
0
    }
1227
0
    yyjson_mut_obj_add_val(doc, features[i], "bbox", bbox);
1228
0
  }
1229
0
}
1230
1231
//! Turns one row into a GeoJSON Feature: the geometry column becomes "geometry", the ID_COLUMN column becomes
1232
//! "id", and every other column becomes a member of "properties".
1233
0
static void JSONCopyToGeoJSONFunction(DataChunk &args, ExpressionState &state, Vector &result) {
1234
0
  auto &func_expr = state.expr.Cast<BoundFunctionExpression>();
1235
0
  auto &info = func_expr.BindInfo()->Cast<JSONCopyToGeoJSONFunctionData>();
1236
0
  auto &lstate = JSONFunctionLocalState::ResetAndGet(state);
1237
0
  auto alc = lstate.json_allocator->GetYYAlc();
1238
0
  auto options = info.formats->GetFormatOptions(state.GetContext());
1239
0
  options.geometry_format = JSONGeometryFormat::GEOJSON;
1240
1241
0
  const auto count = args.size();
1242
0
  auto &payload = args.data[0];
1243
0
  auto &payload_type = payload.GetType();
1244
0
  auto &entries = StructVector::GetEntries(payload);
1245
0
  auto &names = info.formats->const_struct_names;
1246
1247
0
  auto doc = JSONCommon::CreateDocument(alc);
1248
0
  auto features = JSONCommon::AllocateArray<yyjson_mut_val *>(doc, count);
1249
0
  auto properties = JSONCommon::AllocateArray<yyjson_mut_val *>(doc, count);
1250
0
  for (idx_t i = 0; i < count; i++) {
1251
0
    features[i] = yyjson_mut_obj(doc);
1252
0
    yyjson_mut_obj_add_str(doc, features[i], "type", "Feature");
1253
0
    properties[i] = yyjson_mut_obj(doc);
1254
0
  }
1255
1256
0
  auto nested_vals = JSONCommon::AllocateArray<yyjson_mut_val *>(doc, count);
1257
1258
0
  if (info.id_index.IsValid()) {
1259
0
    CreateValues(names, doc, nested_vals, entries[info.id_index.GetIndex()], count, options);
1260
0
    for (idx_t i = 0; i < count; i++) {
1261
0
      yyjson_mut_obj_add_val(doc, features[i], "id", nested_vals[i]);
1262
0
    }
1263
0
  }
1264
1265
0
  if (info.geometry_index.IsValid()) {
1266
0
    auto &geometry_v = entries[info.geometry_index.GetIndex()];
1267
0
    CreateValues(names, doc, nested_vals, geometry_v, count, options);
1268
0
    for (idx_t i = 0; i < count; i++) {
1269
0
      yyjson_mut_obj_add_val(doc, features[i], "geometry", nested_vals[i]);
1270
0
    }
1271
0
    if (info.write_bbox) {
1272
0
      AddGeoJSONBoundingBoxes(doc, features, geometry_v, count);
1273
0
    }
1274
0
  } else {
1275
    // A Feature without a geometry is still valid GeoJSON, it is simply unlocated
1276
0
    for (idx_t i = 0; i < count; i++) {
1277
0
      yyjson_mut_obj_add_null(doc, features[i], "geometry");
1278
0
    }
1279
0
  }
1280
1281
0
  for (const auto property_index : info.property_indices) {
1282
0
    Vector key_v(Value(StructType::GetChildName(payload_type, property_index).GetIdentifierName()), count_t(count));
1283
0
    CreateKeyValuePairs(names, doc, properties, nested_vals, key_v, entries[property_index], count, options);
1284
0
  }
1285
0
  for (idx_t i = 0; i < count; i++) {
1286
0
    yyjson_mut_obj_add_val(doc, features[i], "properties", properties[i]);
1287
0
  }
1288
1289
0
  auto objects = FlatVector::GetDataMutable<string_t>(result);
1290
0
  auto &result_validity = FlatVector::ValidityMutable(result);
1291
0
  UnifiedVectorFormat payload_data;
1292
0
  payload.ToUnifiedFormat(payload_data);
1293
0
  for (idx_t i = 0; i < count; i++) {
1294
0
    const auto idx = payload_data.sel->get_index(i);
1295
0
    if (payload_data.validity.RowIsValid(idx)) {
1296
0
      objects[i] = JSONCommon::WriteVal<yyjson_mut_val>(features[i], alc);
1297
0
    } else {
1298
0
      result_validity.SetInvalid(i);
1299
0
    }
1300
0
  }
1301
0
  if (payload.GetVectorType() == VectorType::CONSTANT_VECTOR || count == 1) {
1302
0
    result.SetVectorType(VectorType::CONSTANT_VECTOR);
1303
0
  }
1304
1305
0
  JSONAllocator::AddBuffer(result, alc);
1306
0
}
1307
1308
//! The column-selecting options are three-state: a NULL argument means the option was not given (use the default
1309
//! behavior), an empty string means it was explicitly unset, and anything else names a column
1310
0
static bool TryGetGeoJSONColumnOption(ClientContext &context, const Expression &argument, string &result) {
1311
0
  if (!argument.IsFoldable()) {
1312
0
    throw BinderException("%s column options must be constants", JSON_COPY_TO_GEOJSON_INTERNAL_NAME);
1313
0
  }
1314
0
  const auto value = ExpressionExecutor::EvaluateScalar(context, argument);
1315
0
  if (value.IsNull()) {
1316
0
    return false;
1317
0
  }
1318
0
  if (value.type().id() != LogicalTypeId::VARCHAR) {
1319
0
    throw BinderException("%s column options must be VARCHAR or NULL", JSON_COPY_TO_GEOJSON_INTERNAL_NAME);
1320
0
  }
1321
0
  result = StringValue::Get(value);
1322
0
  return true;
1323
0
}
1324
1325
//! Look up a column that the user named in a COPY option
1326
static optional_idx FindGeoJSONColumn(const child_list_t<LogicalType> &child_types, const string &name,
1327
0
                                      const char *option_name) {
1328
0
  for (idx_t i = 0; i < child_types.size(); i++) {
1329
0
    if (child_types[i].first == name) {
1330
0
      return i;
1331
0
    }
1332
0
  }
1333
0
  vector<string> available;
1334
0
  for (const auto &child_type : child_types) {
1335
0
    available.push_back(child_type.first.GetIdentifierName());
1336
0
  }
1337
0
  throw BinderException("COPY ... TO ... (FORMAT GEOJSON) option %s refers to column \"%s\", which is not being "
1338
0
                        "written. Available columns: %s",
1339
0
                        option_name, name, StringUtil::Join(available, ", "));
1340
0
}
1341
1342
template <class INPUT>
1343
0
static unique_ptr<FunctionData> JSONCopyToGeoJSONBind(INPUT &input) {
1344
0
  auto &bound_function = input.GetBoundFunction();
1345
0
  auto &arguments = input.GetArguments();
1346
0
  if (arguments.size() != 6) {
1347
0
    throw BinderException("%s is for internal use only", JSON_COPY_TO_GEOJSON_INTERNAL_NAME);
1348
0
  }
1349
0
  if (arguments[0]->HasParameter()) {
1350
0
    throw ParameterNotResolvedException();
1351
0
  }
1352
0
  auto &payload_type = arguments[0]->GetReturnType();
1353
0
  if (payload_type.id() != LogicalTypeId::STRUCT) {
1354
0
    throw BinderException("%s is for internal use only", JSON_COPY_TO_GEOJSON_INTERNAL_NAME);
1355
0
  }
1356
0
  auto &child_types = StructType::GetChildTypes(payload_type);
1357
1358
  // GEOMETRY_COLUMN selects the feature geometry, defaulting to the first GEOMETRY column
1359
0
  optional_idx geometry_index;
1360
0
  string geometry_column;
1361
0
  if (TryGetGeoJSONColumnOption(input.GetClientContext(), *arguments[3], geometry_column)) {
1362
0
    if (!geometry_column.empty()) {
1363
0
      geometry_index = FindGeoJSONColumn(child_types, geometry_column, "GEOMETRY_COLUMN");
1364
0
      if (child_types[geometry_index.GetIndex()].second.id() != LogicalTypeId::GEOMETRY) {
1365
0
        throw BinderException("COPY ... TO ... (FORMAT GEOJSON) option GEOMETRY_COLUMN refers to column "
1366
0
                              "\"%s\", which has type %s instead of GEOMETRY",
1367
0
                              geometry_column, child_types[geometry_index.GetIndex()].second.ToString());
1368
0
      }
1369
0
    }
1370
0
  } else {
1371
0
    for (idx_t i = 0; i < child_types.size(); i++) {
1372
0
      if (child_types[i].second.id() == LogicalTypeId::GEOMETRY) {
1373
0
        geometry_index = i;
1374
0
        break;
1375
0
      }
1376
0
    }
1377
0
    if (!geometry_index.IsValid()) {
1378
0
      throw BinderException(
1379
0
          "COPY ... TO ... (FORMAT GEOJSON) requires a GEOMETRY column, but none of the columns "
1380
0
          "being written has type GEOMETRY."
1381
0
          "\n Use GEOMETRY_COLUMN NULL to write features without a geometry instead.");
1382
0
    }
1383
0
  }
1384
1385
  // ID_COLUMN selects the Feature-level "id", defaulting to a column named "id" if there is one, so that a
1386
  // GeoJSON file read by DuckDB round-trips without needing the option
1387
0
  optional_idx id_index;
1388
0
  string id_column;
1389
0
  if (TryGetGeoJSONColumnOption(input.GetClientContext(), *arguments[4], id_column)) {
1390
0
    if (!id_column.empty()) {
1391
0
      id_index = FindGeoJSONColumn(child_types, id_column, "ID_COLUMN");
1392
0
    }
1393
0
  } else {
1394
0
    for (idx_t i = 0; i < child_types.size(); i++) {
1395
0
      if (child_types[i].first == "id") {
1396
0
        id_index = i;
1397
0
        break;
1398
0
      }
1399
0
    }
1400
0
  }
1401
0
  if (geometry_index.IsValid() && id_index.IsValid() && geometry_index.GetIndex() == id_index.GetIndex()) {
1402
0
    throw BinderException("COPY ... TO ... (FORMAT GEOJSON) cannot write the same column as both the geometry "
1403
0
                          "and the Feature id");
1404
0
  }
1405
1406
  // Everything that is not the geometry or the id becomes a property
1407
0
  vector<idx_t> property_indices;
1408
0
  for (idx_t i = 0; i < child_types.size(); i++) {
1409
0
    if ((geometry_index.IsValid() && geometry_index.GetIndex() == i) ||
1410
0
        (id_index.IsValid() && id_index.GetIndex() == i)) {
1411
0
      continue;
1412
0
    }
1413
0
    property_indices.push_back(i);
1414
0
  }
1415
1416
  // like the column options, a NULL write_bbox means the option was not given
1417
0
  const auto write_bbox_value = input.GetConstant(5);
1418
0
  const auto write_bbox = !write_bbox_value.IsNull() && BooleanValue::Get(write_bbox_value);
1419
1420
0
  StructNames const_struct_names;
1421
0
  auto &bound_arguments = bound_function.GetArguments();
1422
0
  bound_arguments[0] = GetJSONType(const_struct_names, payload_type);
1423
0
  bound_function.SetReturnType(LogicalType::JSON());
1424
1425
0
  auto formats = CreateJSONCopyToJSONFunctionData(input.GetClientContext(), std::move(const_struct_names),
1426
0
                                                  *arguments[1], *arguments[2]);
1427
0
  return make_uniq<JSONCopyToGeoJSONFunctionData>(std::move(formats), geometry_index, id_index,
1428
0
                                                  std::move(property_indices), write_bbox);
1429
0
}
Unexecuted instantiation: json_create.cpp:duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::JSONCopyToGeoJSONBind<duckdb::BindScalarFunctionInput>(duckdb::BindScalarFunctionInput&)
Unexecuted instantiation: json_create.cpp:duckdb::unique_ptr<duckdb::FunctionData, std::__1::default_delete<duckdb::FunctionData>, true> duckdb::JSONCopyToGeoJSONBind<duckdb::ResolveScalarFunctionTypesInput>(duckdb::ResolveScalarFunctionTypesInput&)
1430
1431
static void JSONCopyToJSONSerialize(Serializer &serializer, optional_ptr<FunctionData> bind_data,
1432
0
                                    const BoundScalarFunction &) {
1433
0
  if (!bind_data) {
1434
0
    throw InternalException("%s is missing bind data during serialization", JSON_COPY_TO_JSON_INTERNAL_NAME);
1435
0
  }
1436
0
  auto &data = bind_data->Cast<JSONCopyToJSONFunctionData>();
1437
0
  serializer.WriteProperty(100, "has_date_format", data.has_date_format);
1438
0
  serializer.WriteProperty(101, "date_format", data.date_format_string);
1439
0
  serializer.WriteProperty(102, "has_timestamp_format", data.has_timestamp_format);
1440
0
  serializer.WriteProperty(103, "timestamp_format", data.timestamp_format_string);
1441
0
}
1442
1443
0
static unique_ptr<FunctionData> JSONCopyToJSONDeserialize(Deserializer &deserializer, BoundScalarFunction &function) {
1444
0
  auto has_date_format = deserializer.ReadProperty<bool>(100, "has_date_format");
1445
0
  auto date_format_string = deserializer.ReadProperty<string>(101, "date_format");
1446
0
  auto has_timestamp_format = deserializer.ReadProperty<bool>(102, "has_timestamp_format");
1447
0
  auto timestamp_format_string = deserializer.ReadProperty<string>(103, "timestamp_format");
1448
1449
0
  auto &arguments = function.GetArguments();
1450
0
  if (arguments.size() != 3) {
1451
0
    throw InternalException("%s must have exactly three arguments during deserialization",
1452
0
                            JSON_COPY_TO_JSON_INTERNAL_NAME);
1453
0
  }
1454
1455
0
  StructNames const_struct_names;
1456
0
  GetJSONType(const_struct_names, arguments[0]);
1457
1458
0
  auto &context = deserializer.Get<ClientContext &>();
1459
0
  return CreateJSONCopyToJSONFunctionData(context, std::move(const_struct_names), has_date_format,
1460
0
                                          std::move(date_format_string), has_timestamp_format,
1461
0
                                          std::move(timestamp_format_string));
1462
0
}
1463
1464
unique_ptr<Expression> JSONFunctions::CreateJSONCopyToJSONExpression(ClientContext &context,
1465
                                                                     unique_ptr<Expression> payload,
1466
                                                                     unique_ptr<Expression> date_format,
1467
0
                                                                     unique_ptr<Expression> timestamp_format) {
1468
0
  StructNames const_struct_names;
1469
0
  auto json_type = GetJSONType(const_struct_names, payload->GetReturnType());
1470
0
  auto bind_data =
1471
0
      CreateJSONCopyToJSONFunctionData(context, std::move(const_struct_names), *date_format, *timestamp_format);
1472
1473
0
  payload = BoundCastExpression::AddCastToType(context, std::move(payload), json_type);
1474
1475
0
  vector<unique_ptr<Expression>> children;
1476
0
  children.push_back(std::move(payload));
1477
0
  children.push_back(std::move(date_format));
1478
0
  children.push_back(std::move(timestamp_format));
1479
1480
0
  auto function = GetJSONCopyToJSONFunction();
1481
0
  BoundScalarFunction bound_function(function);
1482
0
  auto &arguments = bound_function.GetArguments();
1483
0
  arguments.clear();
1484
0
  arguments.push_back(std::move(json_type));
1485
0
  arguments.push_back(LogicalType::VARCHAR);
1486
0
  arguments.push_back(LogicalType::VARCHAR);
1487
0
  bound_function.SetReturnType(LogicalType::JSON());
1488
1489
0
  return make_uniq<BoundFunctionExpression>(std::move(bound_function), std::move(children), std::move(bind_data));
1490
0
}
1491
1492
14.8k
ScalarFunctionSet JSONFunctions::GetObjectFunction() {
1493
14.8k
  ScalarFunction fun("json_object", {}, LogicalType::JSON(), ObjectFunction, JSONObjectBind<BindScalarFunctionInput>,
1494
14.8k
                     nullptr, JSONFunctionLocalState::Init);
1495
14.8k
  fun.GetSignature().AddArgs("args", LogicalType::ANY);
1496
14.8k
  fun.SetResolveTypesCallback(JSONCreateResolveTypes<JSONObjectBind<ResolveScalarFunctionTypesInput>>);
1497
14.8k
  fun.SetNullHandling(FunctionNullHandling::SPECIAL_HANDLING);
1498
  // throws if a key is NULL
1499
14.8k
  fun.SetFallible();
1500
14.8k
  return ScalarFunctionSet(fun);
1501
14.8k
}
1502
1503
14.8k
ScalarFunctionSet JSONFunctions::GetArrayFunction() {
1504
14.8k
  ScalarFunction fun("json_array", {}, LogicalType::JSON(), ArrayFunction, JSONArrayBind<BindScalarFunctionInput>,
1505
14.8k
                     nullptr, JSONFunctionLocalState::Init);
1506
14.8k
  fun.GetSignature().AddArgs("args", LogicalType::ANY);
1507
14.8k
  fun.SetResolveTypesCallback(JSONCreateResolveTypes<JSONArrayBind<ResolveScalarFunctionTypesInput>>);
1508
14.8k
  fun.SetNullHandling(FunctionNullHandling::SPECIAL_HANDLING);
1509
14.8k
  fun.SetFallible();
1510
14.8k
  return ScalarFunctionSet(fun);
1511
14.8k
}
1512
1513
14.8k
ScalarFunctionSet JSONFunctions::GetToJSONFunction() {
1514
14.8k
  ScalarFunction fun("to_json", {}, LogicalType::JSON(), ToJSONFunction, ToJSONBind<BindScalarFunctionInput>, nullptr,
1515
14.8k
                     JSONFunctionLocalState::Init);
1516
14.8k
  fun.GetSignature().AddArgs("args", LogicalType::ANY);
1517
14.8k
  fun.SetResolveTypesCallback(JSONCreateResolveTypes<ToJSONBind<ResolveScalarFunctionTypesInput>>);
1518
14.8k
  fun.SetFallible();
1519
14.8k
  return ScalarFunctionSet(fun);
1520
14.8k
}
1521
1522
14.8k
ScalarFunction JSONFunctions::GetJSONCopyToJSONFunction() {
1523
14.8k
  ScalarFunction fun(JSON_COPY_TO_JSON_INTERNAL_NAME, {LogicalType::ANY, LogicalType::VARCHAR, LogicalType::VARCHAR},
1524
14.8k
                     LogicalType::JSON(), JSONCopyToJSONFunction, JSONCopyToJSONBind, nullptr,
1525
14.8k
                     JSONFunctionLocalState::Init);
1526
14.8k
  fun.GetSignature().GetParameter(0).SetName("value");
1527
14.8k
  fun.GetSignature().GetParameter(1).SetName("date_format");
1528
14.8k
  fun.GetSignature().GetParameter(2).SetName("timestamp_format");
1529
14.8k
  fun.SetNullHandling(FunctionNullHandling::SPECIAL_HANDLING);
1530
  // formatting dates and timestamps can fail
1531
14.8k
  fun.SetFallible();
1532
14.8k
  fun.SetSerializeCallback(JSONCopyToJSONSerialize);
1533
14.8k
  fun.SetDeserializeCallback(JSONCopyToJSONDeserialize);
1534
14.8k
  return fun;
1535
14.8k
}
1536
1537
14.8k
ScalarFunction JSONFunctions::GetJSONCopyToGeoJSONFunction() {
1538
14.8k
  ScalarFunction fun(JSON_COPY_TO_GEOJSON_INTERNAL_NAME,
1539
14.8k
                     {LogicalType::ANY, LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::VARCHAR,
1540
14.8k
                      LogicalType::VARCHAR, LogicalType::BOOLEAN},
1541
14.8k
                     LogicalType::JSON(), JSONCopyToGeoJSONFunction, JSONCopyToGeoJSONBind<BindScalarFunctionInput>,
1542
14.8k
                     nullptr, JSONFunctionLocalState::Init);
1543
14.8k
  fun.GetSignature().GetParameter(0).SetName("value");
1544
14.8k
  fun.GetSignature().GetParameter(1).SetName("date_format");
1545
14.8k
  fun.GetSignature().GetParameter(2).SetName("timestamp_format");
1546
14.8k
  fun.GetSignature().GetParameter(3).SetName("geometry_column");
1547
14.8k
  fun.GetSignature().GetParameter(4).SetName("id_column");
1548
14.8k
  fun.GetSignature().GetParameter(5).SetName("write_bbox");
1549
14.8k
  fun.SetResolveTypesCallback(JSONCreateResolveTypes<JSONCopyToGeoJSONBind<ResolveScalarFunctionTypesInput>>);
1550
14.8k
  fun.SetNullHandling(FunctionNullHandling::SPECIAL_HANDLING);
1551
14.8k
  fun.SetFallible();
1552
14.8k
  return fun;
1553
14.8k
}
1554
1555
14.8k
ScalarFunctionSet JSONFunctions::GetArrayToJSONFunction() {
1556
14.8k
  ScalarFunction fun("array_to_json", {}, LogicalType::JSON(), ToJSONFunction,
1557
14.8k
                     ArrayToJSONBind<BindScalarFunctionInput>, nullptr, JSONFunctionLocalState::Init);
1558
14.8k
  fun.GetSignature().AddArgs("args", LogicalType::ANY);
1559
14.8k
  fun.SetResolveTypesCallback(JSONCreateResolveTypes<ArrayToJSONBind<ResolveScalarFunctionTypesInput>>);
1560
14.8k
  fun.SetFallible();
1561
14.8k
  return ScalarFunctionSet(fun);
1562
14.8k
}
1563
1564
14.8k
ScalarFunctionSet JSONFunctions::GetRowToJSONFunction() {
1565
14.8k
  ScalarFunction fun("row_to_json", {}, LogicalType::JSON(), ToJSONFunction, RowToJSONBind<BindScalarFunctionInput>,
1566
14.8k
                     nullptr, JSONFunctionLocalState::Init);
1567
14.8k
  fun.GetSignature().AddArgs("args", LogicalType::ANY);
1568
14.8k
  fun.SetResolveTypesCallback(JSONCreateResolveTypes<RowToJSONBind<ResolveScalarFunctionTypesInput>>);
1569
14.8k
  fun.SetFallible();
1570
14.8k
  return ScalarFunctionSet(fun);
1571
14.8k
}
1572
1573
struct NestedToJSONCastData : public BoundCastData {
1574
public:
1575
0
  explicit NestedToJSONCastData(Context &context_p) : context(context_p) {
1576
0
  }
1577
1578
0
  unique_ptr<BoundCastData> Copy() const override {
1579
0
    auto result = make_uniq<NestedToJSONCastData>(context);
1580
0
    result->const_struct_names = const_struct_names.Copy();
1581
0
    return std::move(result);
1582
0
  }
1583
1584
public:
1585
  Context &context;
1586
  StructNames const_struct_names;
1587
};
1588
1589
0
static bool AnyToJSONCast(Vector &source, Vector &result, idx_t count, CastParameters &parameters) {
1590
0
  auto &lstate = parameters.local_state->Cast<JSONFunctionLocalState>();
1591
0
  lstate.json_allocator->Reset();
1592
0
  auto alc = lstate.json_allocator->GetYYAlc();
1593
0
  auto &cast_data = parameters.cast_data->Cast<NestedToJSONCastData>();
1594
0
  const auto &names = cast_data.const_struct_names;
1595
1596
0
  JSONCopyFormatOptions options;
1597
0
  options.context = cast_data.context;
1598
0
  options.geometry_format = ClientGeometryFormat(cast_data.context);
1599
0
  ToJSONFunctionInternal(names, source, count, result, alc, options);
1600
0
  return true;
1601
0
}
1602
1603
0
static BoundCastInfo AnyToJSONCastBind(BindCastInput &input, const LogicalType &source, const LogicalType &target) {
1604
0
  auto cast_data = make_uniq<NestedToJSONCastData>(input.GetContext());
1605
0
  GetJSONType(cast_data->const_struct_names, source);
1606
0
  return BoundCastInfo(AnyToJSONCast, std::move(cast_data), JSONFunctionLocalState::InitCastLocalState);
1607
0
}
1608
1609
14.8k
void JSONFunctions::RegisterJSONCreateCastFunctions(ExtensionLoader &loader) {
1610
  // Anything can be cast to JSON
1611
595k
  for (const auto &type : LogicalType::AllTypes()) {
1612
595k
    LogicalType source_type;
1613
595k
    switch (type.id()) {
1614
14.8k
    case LogicalTypeId::STRUCT:
1615
14.8k
      source_type = LogicalType::STRUCT({{"any", LogicalType::ANY}});
1616
14.8k
      break;
1617
14.8k
    case LogicalTypeId::TUPLE:
1618
14.8k
      source_type = LogicalType::TUPLE({LogicalType::ANY});
1619
14.8k
      break;
1620
14.8k
    case LogicalTypeId::LIST:
1621
14.8k
      source_type = LogicalType::LIST(LogicalType::ANY);
1622
14.8k
      break;
1623
14.8k
    case LogicalTypeId::MAP:
1624
14.8k
      source_type = LogicalType::MAP(LogicalType::ANY, LogicalType::ANY);
1625
14.8k
      break;
1626
14.8k
    case LogicalTypeId::UNION:
1627
14.8k
      source_type = LogicalType::UNION({{"any", LogicalType::ANY}});
1628
14.8k
      break;
1629
14.8k
    case LogicalTypeId::ARRAY:
1630
14.8k
      source_type = LogicalType::ARRAY(LogicalType::ANY, optional_idx());
1631
14.8k
      break;
1632
14.8k
    case LogicalTypeId::VARCHAR:
1633
      // We skip this one here as it's handled in json_functions.cpp
1634
14.8k
      continue;
1635
491k
    default:
1636
491k
      source_type = type;
1637
595k
    }
1638
    // We prefer going to JSON over going to VARCHAR if a function can do either
1639
580k
    const auto source_to_json_cost = MaxValue<int64_t>(
1640
580k
        CastFunctionSet::ImplicitCastCost(loader.GetDatabaseInstance(), source_type, LogicalType::VARCHAR) - 1, 0);
1641
580k
    loader.RegisterCastFunction(source_type, LogicalType::JSON(), AnyToJSONCastBind, source_to_json_cost);
1642
580k
  }
1643
14.8k
}
1644
1645
} // namespace duckdb