duckdb 0.7.2-dev654.0 → 0.7.2-dev832.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/binding.gyp +2 -0
  2. package/lib/duckdb.d.ts +12 -1
  3. package/lib/duckdb.js +19 -0
  4. package/package.json +1 -1
  5. package/src/duckdb/extension/json/include/json_common.hpp +1 -0
  6. package/src/duckdb/extension/json/include/json_functions.hpp +2 -0
  7. package/src/duckdb/extension/json/include/json_serializer.hpp +77 -0
  8. package/src/duckdb/extension/json/json_functions/json_serialize_sql.cpp +147 -0
  9. package/src/duckdb/extension/json/json_functions.cpp +12 -4
  10. package/src/duckdb/extension/json/json_scan.cpp +2 -2
  11. package/src/duckdb/extension/json/json_serializer.cpp +217 -0
  12. package/src/duckdb/src/common/enums/expression_type.cpp +8 -222
  13. package/src/duckdb/src/common/enums/join_type.cpp +3 -22
  14. package/src/duckdb/src/common/exception.cpp +2 -2
  15. package/src/duckdb/src/common/serializer/enum_serializer.cpp +1172 -0
  16. package/src/duckdb/src/common/types/column_data_collection_segment.cpp +11 -6
  17. package/src/duckdb/src/common/types/value.cpp +117 -0
  18. package/src/duckdb/src/common/types/vector.cpp +140 -1
  19. package/src/duckdb/src/common/types.cpp +166 -89
  20. package/src/duckdb/src/common/vector_operations/vector_cast.cpp +2 -1
  21. package/src/duckdb/src/execution/aggregate_hashtable.cpp +10 -5
  22. package/src/duckdb/src/execution/expression_executor/execute_cast.cpp +2 -1
  23. package/src/duckdb/src/execution/index/art/art.cpp +5 -5
  24. package/src/duckdb/src/execution/operator/persistent/base_csv_reader.cpp +3 -0
  25. package/src/duckdb/src/execution/partitionable_hashtable.cpp +14 -2
  26. package/src/duckdb/src/function/cast/cast_function_set.cpp +1 -1
  27. package/src/duckdb/src/function/cast/enum_casts.cpp +25 -3
  28. package/src/duckdb/src/function/cast/list_casts.cpp +17 -4
  29. package/src/duckdb/src/function/cast/map_cast.cpp +5 -2
  30. package/src/duckdb/src/function/cast/string_cast.cpp +36 -10
  31. package/src/duckdb/src/function/cast/struct_cast.cpp +23 -3
  32. package/src/duckdb/src/function/cast/union_casts.cpp +33 -7
  33. package/src/duckdb/src/function/scalar/string/regexp/regexp_extract_all.cpp +243 -0
  34. package/src/duckdb/src/function/scalar/string/regexp/regexp_util.cpp +79 -0
  35. package/src/duckdb/src/function/scalar/string/regexp.cpp +21 -80
  36. package/src/duckdb/src/function/table/arrow_conversion.cpp +7 -1
  37. package/src/duckdb/src/function/table/table_scan.cpp +1 -1
  38. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  39. package/src/duckdb/src/include/duckdb/common/enums/aggregate_handling.hpp +2 -0
  40. package/src/duckdb/src/include/duckdb/common/enums/expression_type.hpp +2 -3
  41. package/src/duckdb/src/include/duckdb/common/enums/joinref_type.hpp +2 -0
  42. package/src/duckdb/src/include/duckdb/common/enums/order_type.hpp +2 -0
  43. package/src/duckdb/src/include/duckdb/common/enums/set_operation_type.hpp +2 -1
  44. package/src/duckdb/src/include/duckdb/common/exception.hpp +40 -9
  45. package/src/duckdb/src/include/duckdb/common/optional_ptr.hpp +45 -0
  46. package/src/duckdb/src/include/duckdb/common/preserved_error.hpp +3 -0
  47. package/src/duckdb/src/include/duckdb/common/serializer/enum_serializer.hpp +113 -0
  48. package/src/duckdb/src/include/duckdb/common/serializer/format_deserializer.hpp +336 -0
  49. package/src/duckdb/src/include/duckdb/common/serializer/format_serializer.hpp +268 -0
  50. package/src/duckdb/src/include/duckdb/common/serializer/serialization_traits.hpp +126 -0
  51. package/src/duckdb/src/include/duckdb/common/string_util.hpp +12 -0
  52. package/src/duckdb/src/include/duckdb/common/types/value.hpp +2 -0
  53. package/src/duckdb/src/include/duckdb/common/types/vector.hpp +3 -0
  54. package/src/duckdb/src/include/duckdb/common/types.hpp +8 -2
  55. package/src/duckdb/src/include/duckdb/execution/aggregate_hashtable.hpp +1 -0
  56. package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +2 -2
  57. package/src/duckdb/src/include/duckdb/execution/partitionable_hashtable.hpp +3 -0
  58. package/src/duckdb/src/include/duckdb/function/cast/bound_cast_data.hpp +84 -0
  59. package/src/duckdb/src/include/duckdb/function/cast/cast_function_set.hpp +2 -2
  60. package/src/duckdb/src/include/duckdb/function/cast/default_casts.hpp +28 -64
  61. package/src/duckdb/src/include/duckdb/function/scalar/regexp.hpp +81 -1
  62. package/src/duckdb/src/include/duckdb/main/extension_entries.hpp +1 -0
  63. package/src/duckdb/src/include/duckdb/parser/common_table_expression_info.hpp +2 -0
  64. package/src/duckdb/src/include/duckdb/parser/expression/between_expression.hpp +3 -0
  65. package/src/duckdb/src/include/duckdb/parser/expression/bound_expression.hpp +2 -0
  66. package/src/duckdb/src/include/duckdb/parser/expression/case_expression.hpp +5 -0
  67. package/src/duckdb/src/include/duckdb/parser/expression/cast_expression.hpp +2 -0
  68. package/src/duckdb/src/include/duckdb/parser/expression/collate_expression.hpp +2 -0
  69. package/src/duckdb/src/include/duckdb/parser/expression/columnref_expression.hpp +2 -0
  70. package/src/duckdb/src/include/duckdb/parser/expression/comparison_expression.hpp +2 -0
  71. package/src/duckdb/src/include/duckdb/parser/expression/conjunction_expression.hpp +2 -0
  72. package/src/duckdb/src/include/duckdb/parser/expression/constant_expression.hpp +3 -0
  73. package/src/duckdb/src/include/duckdb/parser/expression/default_expression.hpp +1 -0
  74. package/src/duckdb/src/include/duckdb/parser/expression/function_expression.hpp +2 -0
  75. package/src/duckdb/src/include/duckdb/parser/expression/lambda_expression.hpp +2 -0
  76. package/src/duckdb/src/include/duckdb/parser/expression/operator_expression.hpp +2 -0
  77. package/src/duckdb/src/include/duckdb/parser/expression/parameter_expression.hpp +2 -0
  78. package/src/duckdb/src/include/duckdb/parser/expression/positional_reference_expression.hpp +2 -0
  79. package/src/duckdb/src/include/duckdb/parser/expression/star_expression.hpp +2 -0
  80. package/src/duckdb/src/include/duckdb/parser/expression/subquery_expression.hpp +2 -0
  81. package/src/duckdb/src/include/duckdb/parser/expression/window_expression.hpp +5 -0
  82. package/src/duckdb/src/include/duckdb/parser/parsed_data/sample_options.hpp +2 -0
  83. package/src/duckdb/src/include/duckdb/parser/parsed_expression.hpp +5 -0
  84. package/src/duckdb/src/include/duckdb/parser/query_node/recursive_cte_node.hpp +3 -0
  85. package/src/duckdb/src/include/duckdb/parser/query_node/select_node.hpp +5 -0
  86. package/src/duckdb/src/include/duckdb/parser/query_node/set_operation_node.hpp +3 -0
  87. package/src/duckdb/src/include/duckdb/parser/query_node.hpp +11 -1
  88. package/src/duckdb/src/include/duckdb/parser/result_modifier.hpp +24 -1
  89. package/src/duckdb/src/include/duckdb/parser/sql_statement.hpp +2 -1
  90. package/src/duckdb/src/include/duckdb/parser/statement/select_statement.hpp +6 -1
  91. package/src/duckdb/src/include/duckdb/parser/tableref/basetableref.hpp +4 -0
  92. package/src/duckdb/src/include/duckdb/parser/tableref/emptytableref.hpp +2 -0
  93. package/src/duckdb/src/include/duckdb/parser/tableref/expressionlistref.hpp +3 -0
  94. package/src/duckdb/src/include/duckdb/parser/tableref/joinref.hpp +3 -0
  95. package/src/duckdb/src/include/duckdb/parser/tableref/pivotref.hpp +9 -0
  96. package/src/duckdb/src/include/duckdb/parser/tableref/subqueryref.hpp +3 -0
  97. package/src/duckdb/src/include/duckdb/parser/tableref/table_function_ref.hpp +3 -0
  98. package/src/duckdb/src/include/duckdb/parser/tableref.hpp +3 -1
  99. package/src/duckdb/src/include/duckdb/storage/data_table.hpp +2 -2
  100. package/src/duckdb/src/include/duckdb/storage/index.hpp +4 -3
  101. package/src/duckdb/src/include/duckdb/transaction/local_storage.hpp +2 -2
  102. package/src/duckdb/src/main/extension/extension_install.cpp +7 -2
  103. package/src/duckdb/src/optimizer/deliminator.cpp +1 -1
  104. package/src/duckdb/src/optimizer/filter_combiner.cpp +1 -1
  105. package/src/duckdb/src/optimizer/join_order/join_order_optimizer.cpp +3 -3
  106. package/src/duckdb/src/optimizer/rule/move_constants.cpp +2 -2
  107. package/src/duckdb/src/optimizer/statistics/operator/propagate_filter.cpp +1 -1
  108. package/src/duckdb/src/parser/common_table_expression_info.cpp +19 -0
  109. package/src/duckdb/src/parser/expression/between_expression.cpp +17 -0
  110. package/src/duckdb/src/parser/expression/case_expression.cpp +28 -0
  111. package/src/duckdb/src/parser/expression/cast_expression.cpp +17 -0
  112. package/src/duckdb/src/parser/expression/collate_expression.cpp +16 -0
  113. package/src/duckdb/src/parser/expression/columnref_expression.cpp +15 -0
  114. package/src/duckdb/src/parser/expression/comparison_expression.cpp +16 -0
  115. package/src/duckdb/src/parser/expression/conjunction_expression.cpp +15 -0
  116. package/src/duckdb/src/parser/expression/constant_expression.cpp +14 -0
  117. package/src/duckdb/src/parser/expression/default_expression.cpp +7 -0
  118. package/src/duckdb/src/parser/expression/function_expression.cpp +35 -0
  119. package/src/duckdb/src/parser/expression/lambda_expression.cpp +16 -0
  120. package/src/duckdb/src/parser/expression/operator_expression.cpp +15 -0
  121. package/src/duckdb/src/parser/expression/parameter_expression.cpp +15 -0
  122. package/src/duckdb/src/parser/expression/positional_reference_expression.cpp +14 -0
  123. package/src/duckdb/src/parser/expression/star_expression.cpp +20 -0
  124. package/src/duckdb/src/parser/expression/subquery_expression.cpp +20 -0
  125. package/src/duckdb/src/parser/expression/window_expression.cpp +43 -0
  126. package/src/duckdb/src/parser/parsed_data/sample_options.cpp +22 -10
  127. package/src/duckdb/src/parser/parsed_expression.cpp +72 -0
  128. package/src/duckdb/src/parser/query_node/recursive_cte_node.cpp +21 -0
  129. package/src/duckdb/src/parser/query_node/select_node.cpp +31 -0
  130. package/src/duckdb/src/parser/query_node/set_operation_node.cpp +17 -0
  131. package/src/duckdb/src/parser/query_node.cpp +50 -0
  132. package/src/duckdb/src/parser/result_modifier.cpp +78 -0
  133. package/src/duckdb/src/parser/statement/select_statement.cpp +12 -0
  134. package/src/duckdb/src/parser/tableref/basetableref.cpp +21 -0
  135. package/src/duckdb/src/parser/tableref/emptytableref.cpp +4 -0
  136. package/src/duckdb/src/parser/tableref/expressionlistref.cpp +17 -0
  137. package/src/duckdb/src/parser/tableref/joinref.cpp +25 -0
  138. package/src/duckdb/src/parser/tableref/pivotref.cpp +53 -0
  139. package/src/duckdb/src/parser/tableref/subqueryref.cpp +15 -0
  140. package/src/duckdb/src/parser/tableref/table_function.cpp +17 -0
  141. package/src/duckdb/src/parser/tableref.cpp +46 -0
  142. package/src/duckdb/src/parser/transform/expression/transform_bool_expr.cpp +1 -1
  143. package/src/duckdb/src/parser/transform/expression/transform_function.cpp +1 -1
  144. package/src/duckdb/src/parser/transform/expression/transform_operator.cpp +1 -1
  145. package/src/duckdb/src/parser/transform/expression/transform_subquery.cpp +1 -1
  146. package/src/duckdb/src/planner/binder/expression/bind_subquery_expression.cpp +4 -0
  147. package/src/duckdb/src/planner/binder/statement/bind_copy.cpp +3 -1
  148. package/src/duckdb/src/planner/binder/tableref/plan_joinref.cpp +1 -1
  149. package/src/duckdb/src/planner/expression/bound_expression.cpp +4 -0
  150. package/src/duckdb/src/storage/data_table.cpp +15 -13
  151. package/src/duckdb/src/storage/index.cpp +12 -1
  152. package/src/duckdb/src/storage/local_storage.cpp +20 -23
  153. package/src/duckdb/src/verification/deserialized_statement_verifier.cpp +0 -1
  154. package/src/duckdb/third_party/re2/re2/re2.cc +9 -0
  155. package/src/duckdb/third_party/re2/re2/re2.h +2 -0
  156. package/src/duckdb/ub_extension_json_json_functions.cpp +2 -0
  157. package/src/duckdb/ub_src_common_serializer.cpp +2 -0
  158. package/src/duckdb/ub_src_function_scalar_string_regexp.cpp +4 -0
  159. package/src/duckdb/ub_src_parser.cpp +2 -0
  160. package/src/utils.cpp +12 -0
  161. package/test/extension.test.ts +44 -26
package/binding.gyp CHANGED
@@ -69,6 +69,7 @@
69
69
  "src/duckdb/ub_src_function_scalar_operators.cpp",
70
70
  "src/duckdb/ub_src_function_scalar_sequence.cpp",
71
71
  "src/duckdb/ub_src_function_scalar_string.cpp",
72
+ "src/duckdb/ub_src_function_scalar_string_regexp.cpp",
72
73
  "src/duckdb/ub_src_function_scalar_struct.cpp",
73
74
  "src/duckdb/ub_src_function_scalar_system.cpp",
74
75
  "src/duckdb/ub_src_function_scalar_union.cpp",
@@ -243,6 +244,7 @@
243
244
  "src/duckdb/extension/json/json_common.cpp",
244
245
  "src/duckdb/extension/json/json_functions.cpp",
245
246
  "src/duckdb/extension/json/json_scan.cpp",
247
+ "src/duckdb/extension/json/json_serializer.cpp",
246
248
  "src/duckdb/ub_extension_json_json_functions.cpp",
247
249
  "src/duckdb/extension/json/yyjson/yyjson.cpp"
248
250
  ],
package/lib/duckdb.d.ts CHANGED
@@ -43,17 +43,28 @@ export type ExceptionType =
43
43
  | "Parameter Not Allowed" // parameter types not allowed
44
44
  | "Dependency" // dependency
45
45
  | "Unknown"
46
+ | "HTTP"
46
47
  ;
47
48
 
48
49
  /**
49
50
  * Standard error shape for DuckDB errors
50
51
  */
51
- export interface DuckDbError extends Error {
52
+ export interface _DuckDbError extends Error {
52
53
  errno: -1; // value of ERROR
53
54
  code: 'DUCKDB_NODEJS_ERROR';
54
55
  errorType: ExceptionType;
55
56
  }
56
57
 
58
+ export interface HttpError extends _DuckDbError {
59
+ errorType: 'HTTP';
60
+ statusCode: number;
61
+ response: string;
62
+ reason: string;
63
+ headers: Record<string, string>;
64
+ }
65
+
66
+ export type DuckDbError = HttpError | _DuckDbError;
67
+
57
68
  type Callback<T> = (err: DuckDbError | null, res: T) => void;
58
69
 
59
70
  export type RowData = {
package/lib/duckdb.js CHANGED
@@ -688,3 +688,22 @@ Statement.prototype.stream;
688
688
  * @returns sql contained in statement
689
689
  */
690
690
  Statement.prototype.sql;
691
+
692
+ /**
693
+ * @typedef DuckDbError
694
+ * @type {object}
695
+ * @property {number} errno - -1 for DuckDB errors
696
+ * @property {string} message - Error message
697
+ * @property {string} code - 'DUCKDB_NODEJS_ERROR' for DuckDB errors
698
+ * @property {string} errorType - DuckDB error type code (eg, HTTP, IO, Catalog)
699
+ */
700
+
701
+ /**
702
+ * @typedef HTTPError
703
+ * @type {object}
704
+ * @extends {DuckDbError}
705
+ * @property {number} statusCode - HTTP response status code
706
+ * @property {string} reason - HTTP response reason
707
+ * @property {string} response - HTTP response body
708
+ * @property {object} headers - HTTP headers
709
+ */
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "duckdb",
3
3
  "main": "./lib/duckdb.js",
4
4
  "types": "./lib/duckdb.d.ts",
5
- "version": "0.7.2-dev654.0",
5
+ "version": "0.7.2-dev832.0",
6
6
  "description": "DuckDB node.js API",
7
7
  "gypfile": true,
8
8
  "dependencies": {
@@ -100,6 +100,7 @@ public:
100
100
  static constexpr auto READ_FLAG = YYJSON_READ_ALLOW_INF_AND_NAN | YYJSON_READ_ALLOW_TRAILING_COMMAS;
101
101
  static constexpr auto STOP_READ_FLAG = READ_FLAG | YYJSON_READ_STOP_WHEN_DONE | YYJSON_READ_INSITU;
102
102
  static constexpr auto WRITE_FLAG = YYJSON_WRITE_ALLOW_INF_AND_NAN;
103
+ static constexpr auto WRITE_PRETTY_FLAG = YYJSON_WRITE_ALLOW_INF_AND_NAN | YYJSON_WRITE_PRETTY;
103
104
 
104
105
  public:
105
106
  //! Constant JSON type strings
@@ -54,6 +54,7 @@ public:
54
54
 
55
55
  struct JSONFunctionLocalState : public FunctionLocalState {
56
56
  public:
57
+ explicit JSONFunctionLocalState(Allocator &allocator);
57
58
  explicit JSONFunctionLocalState(ClientContext &context);
58
59
  static unique_ptr<FunctionLocalState> Init(ExpressionState &state, const BoundFunctionExpression &expr,
59
60
  FunctionData *bind_data);
@@ -94,6 +95,7 @@ private:
94
95
  static CreateScalarFunctionInfo GetKeysFunction();
95
96
  static CreateScalarFunctionInfo GetTypeFunction();
96
97
  static CreateScalarFunctionInfo GetValidFunction();
98
+ static CreateScalarFunctionInfo GetSerializeSqlFunction();
97
99
 
98
100
  template <class FUNCTION_INFO>
99
101
  static void AddAliases(const vector<string> &names, FUNCTION_INFO fun, vector<FUNCTION_INFO> &functions) {
@@ -0,0 +1,77 @@
1
+ #pragma once
2
+
3
+ #include "json_common.hpp"
4
+ #include "duckdb/common/serializer/format_serializer.hpp"
5
+
6
+ namespace duckdb {
7
+
8
+ struct JsonSerializer : FormatSerializer {
9
+ private:
10
+ yyjson_mut_doc *doc;
11
+ yyjson_mut_val *current_tag;
12
+ vector<yyjson_mut_val *> stack;
13
+
14
+ // Skip writing property if null
15
+ bool skip_if_null = false;
16
+ // Skip writing property if empty string, empty list or empty map.
17
+ bool skip_if_empty = false;
18
+
19
+ // Get the current json value
20
+ inline yyjson_mut_val *Current() {
21
+ return stack.back();
22
+ };
23
+
24
+ // Either adds a value to the current object with the current tag, or appends it to the current array
25
+ void PushValue(yyjson_mut_val *val);
26
+
27
+ public:
28
+ explicit JsonSerializer(yyjson_mut_doc *doc, bool skip_if_null, bool skip_if_empty)
29
+ : doc(doc), stack({yyjson_mut_obj(doc)}), skip_if_null(skip_if_null), skip_if_empty(skip_if_empty) {
30
+ serialize_enum_as_string = true;
31
+ }
32
+
33
+ yyjson_mut_val *GetRootObject() {
34
+ D_ASSERT(stack.size() == 1); // or we forgot to pop somewhere
35
+ return stack.front();
36
+ };
37
+
38
+ void SetTag(const char *tag) final;
39
+
40
+ //===--------------------------------------------------------------------===//
41
+ // Nested Types Hooks
42
+ //===--------------------------------------------------------------------===//
43
+ void OnOptionalBegin(bool present) final;
44
+ void OnListBegin(idx_t count) final;
45
+ void OnListEnd(idx_t count) final;
46
+ void OnMapBegin(idx_t count) final;
47
+ void OnMapEntryBegin() final;
48
+ void OnMapEntryEnd() final;
49
+ void OnMapKeyBegin() final;
50
+ void OnMapValueBegin() final;
51
+ void OnMapEnd(idx_t count) final;
52
+ void OnObjectBegin() final;
53
+ void OnObjectEnd() final;
54
+
55
+ //===--------------------------------------------------------------------===//
56
+ // Primitive Types
57
+ //===--------------------------------------------------------------------===//
58
+ void WriteNull() final;
59
+ void WriteValue(uint8_t value) final;
60
+ void WriteValue(int8_t value) final;
61
+ void WriteValue(uint16_t value) final;
62
+ void WriteValue(int16_t value) final;
63
+ void WriteValue(uint32_t value) final;
64
+ void WriteValue(int32_t value) final;
65
+ void WriteValue(uint64_t value) final;
66
+ void WriteValue(int64_t value) final;
67
+ void WriteValue(hugeint_t value) final;
68
+ void WriteValue(float value) final;
69
+ void WriteValue(double value) final;
70
+ void WriteValue(interval_t value) final;
71
+ void WriteValue(const string &value) final;
72
+ void WriteValue(const string_t value) final;
73
+ void WriteValue(const char *value) final;
74
+ void WriteValue(bool value) final;
75
+ };
76
+
77
+ } // namespace duckdb
@@ -0,0 +1,147 @@
1
+ #include "json_functions.hpp"
2
+ #include "json_serializer.hpp"
3
+ #include "duckdb/parser/parser.hpp"
4
+ #include "duckdb/execution/expression_executor.hpp"
5
+
6
+ namespace duckdb {
7
+
8
+ struct JsonSerializeBindData : public FunctionData {
9
+ bool skip_if_null = false;
10
+ bool skip_if_empty = false;
11
+ bool format = false;
12
+
13
+ JsonSerializeBindData(bool skip_if_null_p, bool skip_if_empty_p, bool format_p)
14
+ : skip_if_null(skip_if_null_p), skip_if_empty(skip_if_empty_p), format(format_p) {
15
+ }
16
+
17
+ public:
18
+ unique_ptr<FunctionData> Copy() const override {
19
+ return make_unique<JsonSerializeBindData>(skip_if_null, skip_if_empty, format);
20
+ }
21
+ bool Equals(const FunctionData &other_p) const override {
22
+ return true;
23
+ }
24
+ };
25
+
26
+ static unique_ptr<FunctionData> JsonSerializeBind(ClientContext &context, ScalarFunction &bound_function,
27
+ vector<unique_ptr<Expression>> &arguments) {
28
+ if (arguments.empty()) {
29
+ throw BinderException("json_serialize_sql takes at least one argument");
30
+ }
31
+
32
+ if (arguments[0]->return_type != LogicalType::VARCHAR) {
33
+ throw InvalidTypeException("json_serialize_sql first argument must be a VARCHAR");
34
+ }
35
+
36
+ // Optional arguments
37
+
38
+ bool skip_if_null = false;
39
+ bool skip_if_empty = false;
40
+ bool format = false;
41
+
42
+ for (idx_t i = 1; i < arguments.size(); i++) {
43
+ auto &arg = arguments[i];
44
+ if (arg->HasParameter()) {
45
+ throw ParameterNotResolvedException();
46
+ }
47
+ if (!arg->IsFoldable()) {
48
+ throw InvalidInputException("arguments to json_serialize_sql must be constant");
49
+ }
50
+ if (arg->alias == "skip_null") {
51
+ if (arg->return_type.id() != LogicalTypeId::BOOLEAN) {
52
+ throw InvalidTypeException("skip_null argument must be a boolean");
53
+ }
54
+ skip_if_null = BooleanValue::Get(ExpressionExecutor::EvaluateScalar(context, *arg));
55
+ } else if (arg->alias == "skip_empty") {
56
+ if (arg->return_type.id() != LogicalTypeId::BOOLEAN) {
57
+ throw InvalidTypeException("skip_empty argument must be a boolean");
58
+ }
59
+ skip_if_empty = BooleanValue::Get(ExpressionExecutor::EvaluateScalar(context, *arg));
60
+ } else if (arg->alias == "format") {
61
+ if (arg->return_type.id() != LogicalTypeId::BOOLEAN) {
62
+ throw InvalidTypeException("indent argument must be a boolean");
63
+ }
64
+ format = BooleanValue::Get(ExpressionExecutor::EvaluateScalar(context, *arg));
65
+ } else {
66
+ throw BinderException(StringUtil::Format("Unknown argument to json_serialize_sql: %s", arg->alias.c_str()));
67
+ }
68
+ }
69
+ return make_unique<JsonSerializeBindData>(skip_if_null, skip_if_empty, format);
70
+ }
71
+
72
+ static void JsonSerializeFunction(DataChunk &args, ExpressionState &state, Vector &result) {
73
+ auto &local_state = JSONFunctionLocalState::ResetAndGet(state);
74
+ auto alc = local_state.json_allocator.GetYYJSONAllocator();
75
+ auto &inputs = args.data[0];
76
+
77
+ auto &func_expr = (BoundFunctionExpression &)state.expr;
78
+ const auto &info = (JsonSerializeBindData &)*func_expr.bind_info;
79
+
80
+ UnaryExecutor::Execute<string_t, string_t>(inputs, result, args.size(), [&](string_t input) {
81
+ auto doc = JSONCommon::CreateDocument(alc);
82
+ auto result_obj = yyjson_mut_obj(doc);
83
+ yyjson_mut_doc_set_root(doc, result_obj);
84
+
85
+ try {
86
+ auto parser = Parser();
87
+ parser.ParseQuery(input.GetString());
88
+
89
+ auto statements_arr = yyjson_mut_arr(doc);
90
+
91
+ for (auto &statement : parser.statements) {
92
+ if (statement->type != StatementType::SELECT_STATEMENT) {
93
+ throw NotImplementedException("Only SELECT statements can be serialized to json!");
94
+ }
95
+ auto &select = (SelectStatement &)*statement;
96
+ auto serializer = JsonSerializer(doc, info.skip_if_null, info.skip_if_empty);
97
+ select.FormatSerialize(serializer);
98
+ auto json = serializer.GetRootObject();
99
+
100
+ yyjson_mut_arr_append(statements_arr, json);
101
+ }
102
+
103
+ yyjson_mut_obj_add_false(doc, result_obj, "error");
104
+ yyjson_mut_obj_add_val(doc, result_obj, "statements", statements_arr);
105
+ idx_t len;
106
+ auto data = yyjson_mut_val_write_opts(result_obj,
107
+ info.format ? JSONCommon::WRITE_PRETTY_FLAG : JSONCommon::WRITE_FLAG,
108
+ alc, (size_t *)&len, nullptr);
109
+ return StringVector::AddString(result, data, len);
110
+
111
+ } catch (Exception &exception) {
112
+ yyjson_mut_obj_add_true(doc, result_obj, "error");
113
+ yyjson_mut_obj_add_strcpy(doc, result_obj, "error_type",
114
+ StringUtil::Lower(exception.ExceptionTypeToString(exception.type)).c_str());
115
+ yyjson_mut_obj_add_strcpy(doc, result_obj, "error_message", exception.RawMessage().c_str());
116
+
117
+ idx_t len;
118
+ auto data = yyjson_mut_val_write_opts(result_obj,
119
+ info.format ? JSONCommon::WRITE_PRETTY_FLAG : JSONCommon::WRITE_FLAG,
120
+ alc, (size_t *)&len, nullptr);
121
+ return StringVector::AddString(result, data, len);
122
+ }
123
+ });
124
+ }
125
+
126
+ CreateScalarFunctionInfo JSONFunctions::GetSerializeSqlFunction() {
127
+ ScalarFunctionSet set("json_serialize_sql");
128
+ set.AddFunction(ScalarFunction({LogicalType::VARCHAR}, JSONCommon::JSONType(), JsonSerializeFunction,
129
+ JsonSerializeBind, nullptr, nullptr, JSONFunctionLocalState::Init));
130
+
131
+ set.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::BOOLEAN}, JSONCommon::JSONType(),
132
+ JsonSerializeFunction, JsonSerializeBind, nullptr, nullptr,
133
+ JSONFunctionLocalState::Init));
134
+
135
+ set.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::BOOLEAN, LogicalType::BOOLEAN},
136
+ JSONCommon::JSONType(), JsonSerializeFunction, JsonSerializeBind, nullptr, nullptr,
137
+ JSONFunctionLocalState::Init));
138
+
139
+ set.AddFunction(
140
+ ScalarFunction({LogicalType::VARCHAR, LogicalType::BOOLEAN, LogicalType::BOOLEAN, LogicalType::BOOLEAN},
141
+ JSONCommon::JSONType(), JsonSerializeFunction, JsonSerializeBind, nullptr, nullptr,
142
+ JSONFunctionLocalState::Init));
143
+
144
+ return CreateScalarFunctionInfo(set);
145
+ }
146
+
147
+ } // namespace duckdb
@@ -103,7 +103,10 @@ unique_ptr<FunctionData> JSONReadManyFunctionData::Bind(ClientContext &context,
103
103
  return make_unique<JSONReadManyFunctionData>(std::move(paths), std::move(lens));
104
104
  }
105
105
 
106
- JSONFunctionLocalState::JSONFunctionLocalState(ClientContext &context) : json_allocator(BufferAllocator::Get(context)) {
106
+ JSONFunctionLocalState::JSONFunctionLocalState(Allocator &allocator) : json_allocator(allocator) {
107
+ }
108
+ JSONFunctionLocalState::JSONFunctionLocalState(ClientContext &context)
109
+ : JSONFunctionLocalState(BufferAllocator::Get(context)) {
107
110
  }
108
111
 
109
112
  unique_ptr<FunctionLocalState> JSONFunctionLocalState::Init(ExpressionState &state, const BoundFunctionExpression &expr,
@@ -143,6 +146,7 @@ vector<CreateScalarFunctionInfo> JSONFunctions::GetScalarFunctions() {
143
146
  functions.push_back(GetKeysFunction());
144
147
  functions.push_back(GetTypeFunction());
145
148
  functions.push_back(GetValidFunction());
149
+ functions.push_back(GetSerializeSqlFunction());
146
150
 
147
151
  return functions;
148
152
  }
@@ -184,8 +188,12 @@ unique_ptr<TableRef> JSONFunctions::ReadJSONReplacement(ClientContext &context,
184
188
  return std::move(table_function);
185
189
  }
186
190
 
187
- static unique_ptr<FunctionLocalState> InitJSONCastLocalState(ClientContext &context) {
188
- return make_unique<JSONFunctionLocalState>(context);
191
+ static unique_ptr<FunctionLocalState> InitJSONCastLocalState(CastLocalStateParameters &parameters) {
192
+ if (parameters.context) {
193
+ return make_unique<JSONFunctionLocalState>(*parameters.context);
194
+ } else {
195
+ return make_unique<JSONFunctionLocalState>(Allocator::DefaultAllocator());
196
+ }
189
197
  }
190
198
 
191
199
  static bool CastVarcharToJSON(Vector &source, Vector &result, idx_t count, CastParameters &parameters) {
@@ -208,9 +216,9 @@ static bool CastVarcharToJSON(Vector &source, Vector &result, idx_t count, CastP
208
216
  mask.SetInvalid(idx);
209
217
  success = false;
210
218
  }
211
-
212
219
  return input;
213
220
  });
221
+ result.Reinterpret(source);
214
222
  return success;
215
223
  }
216
224
 
@@ -221,7 +221,7 @@ unique_ptr<GlobalTableFunctionState> JSONGlobalTableFunctionState::Init(ClientCo
221
221
  }
222
222
  bind_data.names = std::move(names);
223
223
  }
224
- return result;
224
+ return std::move(result);
225
225
  }
226
226
 
227
227
  idx_t JSONGlobalTableFunctionState::MaxThreads() const {
@@ -262,7 +262,7 @@ unique_ptr<LocalTableFunctionState> JSONLocalTableFunctionState::Init(ExecutionC
262
262
  result->state.transform_options = gstate.state.bind_data.transform_options;
263
263
  result->state.transform_options.date_format_map = &result->state.date_format_map;
264
264
 
265
- return result;
265
+ return std::move(result);
266
266
  }
267
267
 
268
268
  idx_t JSONLocalTableFunctionState::GetBatchIndex() const {
@@ -0,0 +1,217 @@
1
+ #include "json_serializer.hpp"
2
+
3
+ namespace duckdb {
4
+
5
+ void JsonSerializer::PushValue(yyjson_mut_val *val) {
6
+ auto current = Current();
7
+ // Array case, just append the value
8
+ if (yyjson_mut_is_arr(current)) {
9
+ yyjson_mut_arr_append(current, val);
10
+ }
11
+ // Object case, use the currently set tag.
12
+ else if (yyjson_mut_is_obj(current)) {
13
+ yyjson_mut_obj_add(current, current_tag, val);
14
+ }
15
+ // Else throw
16
+ else {
17
+ throw InternalException("Cannot add value to non-array/object json value");
18
+ }
19
+ }
20
+
21
+ void JsonSerializer::SetTag(const char *tag) {
22
+ current_tag = yyjson_mut_strcpy(doc, tag);
23
+ }
24
+
25
+ //===--------------------------------------------------------------------===//
26
+ // Nested types
27
+ //===--------------------------------------------------------------------===//
28
+ void JsonSerializer::OnOptionalBegin(bool present) {
29
+ if (!present && !skip_if_null) {
30
+ WriteNull();
31
+ }
32
+ }
33
+
34
+ void JsonSerializer::OnListBegin(idx_t count) {
35
+ auto new_value = yyjson_mut_arr(doc);
36
+ // We always push a value to the stack, we just don't add it as a child to the current value
37
+ // if skipping empty. Even though it is "unnecessary" to create an empty value just to discard it,
38
+ // this allows the rest of the code to keep on like normal.
39
+ if (!(count == 0 && skip_if_empty)) {
40
+ PushValue(new_value);
41
+ }
42
+ stack.push_back(new_value);
43
+ }
44
+
45
+ void JsonSerializer::OnListEnd(idx_t count) {
46
+ stack.pop_back();
47
+ }
48
+
49
+ // Serialize maps as arrays of objects with "key" and "value" properties.
50
+ void JsonSerializer::OnMapBegin(idx_t count) {
51
+ auto new_value = yyjson_mut_arr(doc);
52
+ if (!(count == 0 && skip_if_empty)) {
53
+ PushValue(new_value);
54
+ }
55
+ stack.push_back(new_value);
56
+ }
57
+
58
+ void JsonSerializer::OnMapEntryBegin() {
59
+ auto new_value = yyjson_mut_obj(doc);
60
+ stack.push_back(new_value);
61
+ }
62
+
63
+ void JsonSerializer::OnMapKeyBegin() {
64
+ SetTag("key");
65
+ }
66
+
67
+ void JsonSerializer::OnMapValueBegin() {
68
+ SetTag("value");
69
+ }
70
+
71
+ void JsonSerializer::OnMapEntryEnd() {
72
+ stack.pop_back();
73
+ }
74
+
75
+ void JsonSerializer::OnMapEnd(idx_t count) {
76
+ stack.pop_back();
77
+ }
78
+
79
+ void JsonSerializer::OnObjectBegin() {
80
+ auto new_value = yyjson_mut_obj(doc);
81
+ PushValue(new_value);
82
+ stack.push_back(new_value);
83
+ }
84
+
85
+ void JsonSerializer::OnObjectEnd() {
86
+ auto obj = Current();
87
+ auto count = yyjson_mut_obj_size(obj);
88
+
89
+ stack.pop_back();
90
+
91
+ if (count == 0 && skip_if_empty && !stack.empty()) {
92
+ // remove obj from parent since it was empty
93
+ auto parent = Current();
94
+ if (yyjson_mut_is_arr(parent)) {
95
+ size_t idx;
96
+ size_t max;
97
+ yyjson_mut_val *item;
98
+ size_t found;
99
+ yyjson_mut_arr_foreach(parent, idx, max, item) {
100
+ if (item == obj) {
101
+ found = idx;
102
+ }
103
+ }
104
+ yyjson_mut_arr_remove(parent, found);
105
+ } else if (yyjson_mut_is_obj(parent)) {
106
+ size_t idx;
107
+ size_t max;
108
+ yyjson_mut_val *item;
109
+ yyjson_mut_val *key;
110
+ const char *found;
111
+ yyjson_mut_obj_foreach(parent, idx, max, key, item) {
112
+ if (item == obj) {
113
+ found = yyjson_mut_get_str(key);
114
+ }
115
+ }
116
+ yyjson_mut_obj_remove_key(parent, found);
117
+ }
118
+ }
119
+ }
120
+
121
+ //===--------------------------------------------------------------------===//
122
+ // Primitive types
123
+ //===--------------------------------------------------------------------===//
124
+ void JsonSerializer::WriteNull() {
125
+ auto val = yyjson_mut_null(doc);
126
+ PushValue(val);
127
+ }
128
+
129
+ void JsonSerializer::WriteValue(uint8_t value) {
130
+ auto val = yyjson_mut_uint(doc, value);
131
+ PushValue(val);
132
+ }
133
+
134
+ void JsonSerializer::WriteValue(int8_t value) {
135
+ auto val = yyjson_mut_sint(doc, value);
136
+ PushValue(val);
137
+ }
138
+
139
+ void JsonSerializer::WriteValue(uint16_t value) {
140
+ auto val = yyjson_mut_uint(doc, value);
141
+ PushValue(val);
142
+ }
143
+
144
+ void JsonSerializer::WriteValue(int16_t value) {
145
+ auto val = yyjson_mut_sint(doc, value);
146
+ PushValue(val);
147
+ }
148
+
149
+ void JsonSerializer::WriteValue(uint32_t value) {
150
+ auto val = yyjson_mut_uint(doc, value);
151
+ PushValue(val);
152
+ }
153
+
154
+ void JsonSerializer::WriteValue(int32_t value) {
155
+ auto val = yyjson_mut_int(doc, value);
156
+ PushValue(val);
157
+ }
158
+
159
+ void JsonSerializer::WriteValue(uint64_t value) {
160
+ auto val = yyjson_mut_uint(doc, value);
161
+ PushValue(val);
162
+ }
163
+
164
+ void JsonSerializer::WriteValue(int64_t value) {
165
+ auto val = yyjson_mut_sint(doc, value);
166
+ PushValue(val);
167
+ }
168
+
169
+ void JsonSerializer::WriteValue(hugeint_t value) {
170
+ throw NotImplementedException("Cannot serialize hugeint_t to json yet!");
171
+ }
172
+
173
+ void JsonSerializer::WriteValue(float value) {
174
+ auto val = yyjson_mut_real(doc, value);
175
+ PushValue(val);
176
+ }
177
+
178
+ void JsonSerializer::WriteValue(double value) {
179
+ auto val = yyjson_mut_real(doc, value);
180
+ PushValue(val);
181
+ }
182
+
183
+ void JsonSerializer::WriteValue(interval_t value) {
184
+ throw NotImplementedException("Cannot serialize interval_t to json yet!");
185
+ }
186
+
187
+ void JsonSerializer::WriteValue(const string &value) {
188
+ if (skip_if_empty && value.empty()) {
189
+ return;
190
+ }
191
+ auto val = yyjson_mut_strcpy(doc, value.c_str());
192
+ PushValue(val);
193
+ }
194
+
195
+ void JsonSerializer::WriteValue(const string_t value) {
196
+ if (skip_if_empty && value.GetSize() == 0) {
197
+ return;
198
+ }
199
+ auto str = value.GetString();
200
+ auto val = yyjson_mut_strcpy(doc, str.c_str());
201
+ PushValue(val);
202
+ }
203
+
204
+ void JsonSerializer::WriteValue(const char *value) {
205
+ if (skip_if_empty && (value == nullptr || value[0] == '\0')) {
206
+ return;
207
+ }
208
+ auto val = yyjson_mut_strcpy(doc, value);
209
+ PushValue(val);
210
+ }
211
+
212
+ void JsonSerializer::WriteValue(bool value) {
213
+ auto val = yyjson_mut_bool(doc, value);
214
+ PushValue(val);
215
+ }
216
+
217
+ } // namespace duckdb