duckdb 0.7.2-dev717.0 → 0.7.2-dev865.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 (179) 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 +1 -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 +1 -0
  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/catalog/catalog.cpp +21 -5
  13. package/src/duckdb/src/common/enums/expression_type.cpp +8 -222
  14. package/src/duckdb/src/common/enums/join_type.cpp +3 -22
  15. package/src/duckdb/src/common/exception.cpp +2 -2
  16. package/src/duckdb/src/common/serializer/enum_serializer.cpp +1172 -0
  17. package/src/duckdb/src/common/types/value.cpp +117 -93
  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/execution/operator/helper/physical_limit.cpp +3 -0
  21. package/src/duckdb/src/execution/physical_plan/plan_aggregate.cpp +5 -8
  22. package/src/duckdb/src/function/scalar/date/date_part.cpp +2 -2
  23. package/src/duckdb/src/function/scalar/date/date_trunc.cpp +2 -2
  24. package/src/duckdb/src/function/scalar/list/list_aggregates.cpp +1 -1
  25. package/src/duckdb/src/function/scalar/list/list_lambdas.cpp +4 -0
  26. package/src/duckdb/src/function/scalar/operators/arithmetic.cpp +8 -8
  27. package/src/duckdb/src/function/scalar/string/regexp/regexp_extract_all.cpp +243 -0
  28. package/src/duckdb/src/function/scalar/string/regexp/regexp_util.cpp +79 -0
  29. package/src/duckdb/src/function/scalar/string/regexp.cpp +21 -80
  30. package/src/duckdb/src/function/table/arrow_conversion.cpp +7 -1
  31. package/src/duckdb/src/function/table/table_scan.cpp +1 -1
  32. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  33. package/src/duckdb/src/include/duckdb/catalog/catalog.hpp +3 -0
  34. package/src/duckdb/src/include/duckdb/common/enums/aggregate_handling.hpp +2 -0
  35. package/src/duckdb/src/include/duckdb/common/enums/expression_type.hpp +2 -3
  36. package/src/duckdb/src/include/duckdb/common/enums/joinref_type.hpp +2 -0
  37. package/src/duckdb/src/include/duckdb/common/enums/order_type.hpp +2 -0
  38. package/src/duckdb/src/include/duckdb/common/enums/set_operation_type.hpp +2 -1
  39. package/src/duckdb/src/include/duckdb/common/exception.hpp +40 -9
  40. package/src/duckdb/src/include/duckdb/common/preserved_error.hpp +3 -0
  41. package/src/duckdb/src/include/duckdb/common/serializer/enum_serializer.hpp +113 -0
  42. package/src/duckdb/src/include/duckdb/common/serializer/format_deserializer.hpp +336 -0
  43. package/src/duckdb/src/include/duckdb/common/serializer/format_serializer.hpp +268 -0
  44. package/src/duckdb/src/include/duckdb/common/serializer/serialization_traits.hpp +126 -0
  45. package/src/duckdb/src/include/duckdb/common/string_util.hpp +12 -0
  46. package/src/duckdb/src/include/duckdb/common/types/value.hpp +2 -31
  47. package/src/duckdb/src/include/duckdb/common/types/vector.hpp +3 -0
  48. package/src/duckdb/src/include/duckdb/common/types.hpp +8 -2
  49. package/src/duckdb/src/include/duckdb/function/scalar/regexp.hpp +81 -1
  50. package/src/duckdb/src/include/duckdb/main/extension_entries.hpp +1 -0
  51. package/src/duckdb/src/include/duckdb/parser/common_table_expression_info.hpp +2 -0
  52. package/src/duckdb/src/include/duckdb/parser/expression/between_expression.hpp +3 -0
  53. package/src/duckdb/src/include/duckdb/parser/expression/bound_expression.hpp +2 -0
  54. package/src/duckdb/src/include/duckdb/parser/expression/case_expression.hpp +5 -0
  55. package/src/duckdb/src/include/duckdb/parser/expression/cast_expression.hpp +2 -0
  56. package/src/duckdb/src/include/duckdb/parser/expression/collate_expression.hpp +2 -0
  57. package/src/duckdb/src/include/duckdb/parser/expression/columnref_expression.hpp +2 -0
  58. package/src/duckdb/src/include/duckdb/parser/expression/comparison_expression.hpp +2 -0
  59. package/src/duckdb/src/include/duckdb/parser/expression/conjunction_expression.hpp +2 -0
  60. package/src/duckdb/src/include/duckdb/parser/expression/constant_expression.hpp +3 -0
  61. package/src/duckdb/src/include/duckdb/parser/expression/default_expression.hpp +1 -0
  62. package/src/duckdb/src/include/duckdb/parser/expression/function_expression.hpp +2 -0
  63. package/src/duckdb/src/include/duckdb/parser/expression/lambda_expression.hpp +2 -0
  64. package/src/duckdb/src/include/duckdb/parser/expression/operator_expression.hpp +2 -0
  65. package/src/duckdb/src/include/duckdb/parser/expression/parameter_expression.hpp +2 -0
  66. package/src/duckdb/src/include/duckdb/parser/expression/positional_reference_expression.hpp +2 -0
  67. package/src/duckdb/src/include/duckdb/parser/expression/star_expression.hpp +2 -0
  68. package/src/duckdb/src/include/duckdb/parser/expression/subquery_expression.hpp +2 -0
  69. package/src/duckdb/src/include/duckdb/parser/expression/window_expression.hpp +5 -0
  70. package/src/duckdb/src/include/duckdb/parser/parsed_data/sample_options.hpp +2 -0
  71. package/src/duckdb/src/include/duckdb/parser/parsed_expression.hpp +5 -0
  72. package/src/duckdb/src/include/duckdb/parser/query_node/recursive_cte_node.hpp +3 -0
  73. package/src/duckdb/src/include/duckdb/parser/query_node/select_node.hpp +5 -0
  74. package/src/duckdb/src/include/duckdb/parser/query_node/set_operation_node.hpp +3 -0
  75. package/src/duckdb/src/include/duckdb/parser/query_node.hpp +11 -1
  76. package/src/duckdb/src/include/duckdb/parser/result_modifier.hpp +24 -1
  77. package/src/duckdb/src/include/duckdb/parser/sql_statement.hpp +2 -1
  78. package/src/duckdb/src/include/duckdb/parser/statement/select_statement.hpp +6 -1
  79. package/src/duckdb/src/include/duckdb/parser/tableref/basetableref.hpp +4 -0
  80. package/src/duckdb/src/include/duckdb/parser/tableref/emptytableref.hpp +2 -0
  81. package/src/duckdb/src/include/duckdb/parser/tableref/expressionlistref.hpp +3 -0
  82. package/src/duckdb/src/include/duckdb/parser/tableref/joinref.hpp +3 -0
  83. package/src/duckdb/src/include/duckdb/parser/tableref/pivotref.hpp +9 -0
  84. package/src/duckdb/src/include/duckdb/parser/tableref/subqueryref.hpp +3 -0
  85. package/src/duckdb/src/include/duckdb/parser/tableref/table_function_ref.hpp +3 -0
  86. package/src/duckdb/src/include/duckdb/parser/tableref.hpp +3 -1
  87. package/src/duckdb/src/include/duckdb/storage/statistics/numeric_stats.hpp +9 -52
  88. package/src/duckdb/src/include/duckdb/storage/statistics/numeric_stats_union.hpp +62 -0
  89. package/src/duckdb/src/include/duckdb/storage/table/column_checkpoint_state.hpp +2 -1
  90. package/src/duckdb/src/include/duckdb/storage/table/column_data.hpp +6 -3
  91. package/src/duckdb/src/include/duckdb/storage/table/column_data_checkpointer.hpp +3 -2
  92. package/src/duckdb/src/include/duckdb/storage/table/column_segment.hpp +5 -3
  93. package/src/duckdb/src/include/duckdb/storage/table/persistent_table_data.hpp +4 -1
  94. package/src/duckdb/src/include/duckdb/storage/table/row_group.hpp +6 -3
  95. package/src/duckdb/src/include/duckdb/storage/table/row_group_collection.hpp +5 -3
  96. package/src/duckdb/src/include/duckdb/storage/table/row_group_segment_tree.hpp +37 -0
  97. package/src/duckdb/src/include/duckdb/storage/table/scan_state.hpp +8 -1
  98. package/src/duckdb/src/include/duckdb/storage/table/segment_base.hpp +4 -3
  99. package/src/duckdb/src/include/duckdb/storage/table/segment_tree.hpp +271 -26
  100. package/src/duckdb/src/main/extension/extension_install.cpp +7 -2
  101. package/src/duckdb/src/optimizer/deliminator.cpp +1 -1
  102. package/src/duckdb/src/optimizer/filter_combiner.cpp +1 -1
  103. package/src/duckdb/src/optimizer/join_order/join_order_optimizer.cpp +3 -3
  104. package/src/duckdb/src/optimizer/rule/move_constants.cpp +2 -2
  105. package/src/duckdb/src/optimizer/statistics/operator/propagate_filter.cpp +1 -1
  106. package/src/duckdb/src/parser/common_table_expression_info.cpp +19 -0
  107. package/src/duckdb/src/parser/expression/between_expression.cpp +17 -0
  108. package/src/duckdb/src/parser/expression/case_expression.cpp +28 -0
  109. package/src/duckdb/src/parser/expression/cast_expression.cpp +17 -0
  110. package/src/duckdb/src/parser/expression/collate_expression.cpp +16 -0
  111. package/src/duckdb/src/parser/expression/columnref_expression.cpp +15 -0
  112. package/src/duckdb/src/parser/expression/comparison_expression.cpp +16 -0
  113. package/src/duckdb/src/parser/expression/conjunction_expression.cpp +15 -0
  114. package/src/duckdb/src/parser/expression/constant_expression.cpp +14 -0
  115. package/src/duckdb/src/parser/expression/default_expression.cpp +7 -0
  116. package/src/duckdb/src/parser/expression/function_expression.cpp +35 -0
  117. package/src/duckdb/src/parser/expression/lambda_expression.cpp +16 -0
  118. package/src/duckdb/src/parser/expression/operator_expression.cpp +15 -0
  119. package/src/duckdb/src/parser/expression/parameter_expression.cpp +15 -0
  120. package/src/duckdb/src/parser/expression/positional_reference_expression.cpp +14 -0
  121. package/src/duckdb/src/parser/expression/star_expression.cpp +20 -0
  122. package/src/duckdb/src/parser/expression/subquery_expression.cpp +20 -0
  123. package/src/duckdb/src/parser/expression/window_expression.cpp +43 -0
  124. package/src/duckdb/src/parser/parsed_data/sample_options.cpp +22 -10
  125. package/src/duckdb/src/parser/parsed_expression.cpp +72 -0
  126. package/src/duckdb/src/parser/query_node/recursive_cte_node.cpp +21 -0
  127. package/src/duckdb/src/parser/query_node/select_node.cpp +31 -0
  128. package/src/duckdb/src/parser/query_node/set_operation_node.cpp +17 -0
  129. package/src/duckdb/src/parser/query_node.cpp +50 -0
  130. package/src/duckdb/src/parser/result_modifier.cpp +78 -0
  131. package/src/duckdb/src/parser/statement/select_statement.cpp +12 -0
  132. package/src/duckdb/src/parser/tableref/basetableref.cpp +21 -0
  133. package/src/duckdb/src/parser/tableref/emptytableref.cpp +4 -0
  134. package/src/duckdb/src/parser/tableref/expressionlistref.cpp +17 -0
  135. package/src/duckdb/src/parser/tableref/joinref.cpp +25 -0
  136. package/src/duckdb/src/parser/tableref/pivotref.cpp +53 -0
  137. package/src/duckdb/src/parser/tableref/subqueryref.cpp +15 -0
  138. package/src/duckdb/src/parser/tableref/table_function.cpp +17 -0
  139. package/src/duckdb/src/parser/tableref.cpp +46 -0
  140. package/src/duckdb/src/parser/transform/expression/transform_array_access.cpp +11 -0
  141. package/src/duckdb/src/parser/transform/expression/transform_bool_expr.cpp +1 -1
  142. package/src/duckdb/src/parser/transform/expression/transform_operator.cpp +1 -1
  143. package/src/duckdb/src/parser/transform/expression/transform_subquery.cpp +1 -1
  144. package/src/duckdb/src/planner/binder/expression/bind_function_expression.cpp +22 -4
  145. package/src/duckdb/src/planner/binder/expression/bind_subquery_expression.cpp +4 -0
  146. package/src/duckdb/src/planner/binder/tableref/plan_joinref.cpp +1 -1
  147. package/src/duckdb/src/planner/expression/bound_expression.cpp +4 -0
  148. package/src/duckdb/src/storage/checkpoint/table_data_reader.cpp +3 -11
  149. package/src/duckdb/src/storage/checkpoint/table_data_writer.cpp +6 -0
  150. package/src/duckdb/src/storage/checkpoint_manager.cpp +1 -0
  151. package/src/duckdb/src/storage/compression/numeric_constant.cpp +2 -2
  152. package/src/duckdb/src/storage/data_table.cpp +1 -1
  153. package/src/duckdb/src/storage/statistics/numeric_stats.cpp +145 -83
  154. package/src/duckdb/src/storage/statistics/numeric_stats_union.cpp +65 -0
  155. package/src/duckdb/src/storage/storage_info.cpp +1 -1
  156. package/src/duckdb/src/storage/table/column_checkpoint_state.cpp +1 -6
  157. package/src/duckdb/src/storage/table/column_data.cpp +29 -35
  158. package/src/duckdb/src/storage/table/column_data_checkpointer.cpp +5 -5
  159. package/src/duckdb/src/storage/table/column_segment.cpp +8 -7
  160. package/src/duckdb/src/storage/table/list_column_data.cpp +2 -1
  161. package/src/duckdb/src/storage/table/persistent_table_data.cpp +2 -1
  162. package/src/duckdb/src/storage/table/row_group.cpp +9 -9
  163. package/src/duckdb/src/storage/table/row_group_collection.cpp +82 -66
  164. package/src/duckdb/src/storage/table/scan_state.cpp +22 -3
  165. package/src/duckdb/src/storage/table/standard_column_data.cpp +1 -0
  166. package/src/duckdb/src/storage/table/struct_column_data.cpp +1 -0
  167. package/src/duckdb/src/verification/deserialized_statement_verifier.cpp +0 -1
  168. package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +11780 -11512
  169. package/src/duckdb/third_party/re2/re2/re2.cc +9 -0
  170. package/src/duckdb/third_party/re2/re2/re2.h +2 -0
  171. package/src/duckdb/ub_extension_json_json_functions.cpp +2 -0
  172. package/src/duckdb/ub_src_common_serializer.cpp +2 -0
  173. package/src/duckdb/ub_src_function_scalar_string_regexp.cpp +4 -0
  174. package/src/duckdb/ub_src_parser.cpp +2 -0
  175. package/src/duckdb/ub_src_storage_statistics.cpp +2 -0
  176. package/src/duckdb/ub_src_storage_table.cpp +0 -2
  177. package/src/utils.cpp +12 -0
  178. package/test/extension.test.ts +44 -26
  179. package/src/duckdb/src/storage/table/segment_tree.cpp +0 -179
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-dev717.0",
5
+ "version": "0.7.2-dev865.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
@@ -95,6 +95,7 @@ private:
95
95
  static CreateScalarFunctionInfo GetKeysFunction();
96
96
  static CreateScalarFunctionInfo GetTypeFunction();
97
97
  static CreateScalarFunctionInfo GetValidFunction();
98
+ static CreateScalarFunctionInfo GetSerializeSqlFunction();
98
99
 
99
100
  template <class FUNCTION_INFO>
100
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
@@ -146,6 +146,7 @@ vector<CreateScalarFunctionInfo> JSONFunctions::GetScalarFunctions() {
146
146
  functions.push_back(GetKeysFunction());
147
147
  functions.push_back(GetTypeFunction());
148
148
  functions.push_back(GetValidFunction());
149
+ functions.push_back(GetSerializeSqlFunction());
149
150
 
150
151
  return functions;
151
152
  }
@@ -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
@@ -63,20 +63,28 @@ Catalog &Catalog::GetSystemCatalog(ClientContext &context) {
63
63
  return Catalog::GetSystemCatalog(*context.db);
64
64
  }
65
65
 
66
- Catalog &Catalog::GetCatalog(ClientContext &context, const string &catalog_name) {
66
+ optional_ptr<Catalog> Catalog::GetCatalogEntry(ClientContext &context, const string &catalog_name) {
67
67
  auto &db_manager = DatabaseManager::Get(context);
68
68
  if (catalog_name == TEMP_CATALOG) {
69
- return ClientData::Get(context).temporary_objects->GetCatalog();
69
+ return &ClientData::Get(context).temporary_objects->GetCatalog();
70
70
  }
71
71
  if (catalog_name == SYSTEM_CATALOG) {
72
- return GetSystemCatalog(context);
72
+ return &GetSystemCatalog(context);
73
73
  }
74
74
  auto entry = db_manager.GetDatabase(
75
75
  context, IsInvalidCatalog(catalog_name) ? DatabaseManager::GetDefaultDatabase(context) : catalog_name);
76
76
  if (!entry) {
77
+ return nullptr;
78
+ }
79
+ return &entry->GetCatalog();
80
+ }
81
+
82
+ Catalog &Catalog::GetCatalog(ClientContext &context, const string &catalog_name) {
83
+ auto catalog = Catalog::GetCatalogEntry(context, catalog_name);
84
+ if (!catalog) {
77
85
  throw BinderException("Catalog \"%s\" does not exist!", catalog_name);
78
86
  }
79
- return entry->GetCatalog();
87
+ return *catalog;
80
88
  }
81
89
 
82
90
  //===--------------------------------------------------------------------===//
@@ -576,7 +584,15 @@ CatalogEntry *Catalog::GetEntry(ClientContext &context, CatalogType type, const
576
584
  vector<CatalogLookup> lookups;
577
585
  lookups.reserve(entries.size());
578
586
  for (auto &entry : entries) {
579
- lookups.emplace_back(Catalog::GetCatalog(context, entry.catalog), entry.schema);
587
+ if (if_exists_p) {
588
+ auto catalog_entry = Catalog::GetCatalogEntry(context, entry.catalog);
589
+ if (!catalog_entry) {
590
+ return nullptr;
591
+ }
592
+ lookups.emplace_back(*catalog_entry, entry.schema);
593
+ } else {
594
+ lookups.emplace_back(Catalog::GetCatalog(context, entry.catalog), entry.schema);
595
+ }
580
596
  }
581
597
  auto result = LookupEntry(context, lookups, type, name, if_exists_p, error_context);
582
598
  if (!result.Found()) {