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.
- package/binding.gyp +2 -0
- package/lib/duckdb.d.ts +12 -1
- package/lib/duckdb.js +19 -0
- package/package.json +1 -1
- package/src/duckdb/extension/json/include/json_common.hpp +1 -0
- package/src/duckdb/extension/json/include/json_functions.hpp +1 -0
- package/src/duckdb/extension/json/include/json_serializer.hpp +77 -0
- package/src/duckdb/extension/json/json_functions/json_serialize_sql.cpp +147 -0
- package/src/duckdb/extension/json/json_functions.cpp +1 -0
- package/src/duckdb/extension/json/json_scan.cpp +2 -2
- package/src/duckdb/extension/json/json_serializer.cpp +217 -0
- package/src/duckdb/src/catalog/catalog.cpp +21 -5
- package/src/duckdb/src/common/enums/expression_type.cpp +8 -222
- package/src/duckdb/src/common/enums/join_type.cpp +3 -22
- package/src/duckdb/src/common/exception.cpp +2 -2
- package/src/duckdb/src/common/serializer/enum_serializer.cpp +1172 -0
- package/src/duckdb/src/common/types/value.cpp +117 -93
- package/src/duckdb/src/common/types/vector.cpp +140 -1
- package/src/duckdb/src/common/types.cpp +166 -89
- package/src/duckdb/src/execution/operator/helper/physical_limit.cpp +3 -0
- package/src/duckdb/src/execution/physical_plan/plan_aggregate.cpp +5 -8
- package/src/duckdb/src/function/scalar/date/date_part.cpp +2 -2
- package/src/duckdb/src/function/scalar/date/date_trunc.cpp +2 -2
- package/src/duckdb/src/function/scalar/list/list_aggregates.cpp +1 -1
- package/src/duckdb/src/function/scalar/list/list_lambdas.cpp +4 -0
- package/src/duckdb/src/function/scalar/operators/arithmetic.cpp +8 -8
- package/src/duckdb/src/function/scalar/string/regexp/regexp_extract_all.cpp +243 -0
- package/src/duckdb/src/function/scalar/string/regexp/regexp_util.cpp +79 -0
- package/src/duckdb/src/function/scalar/string/regexp.cpp +21 -80
- package/src/duckdb/src/function/table/arrow_conversion.cpp +7 -1
- package/src/duckdb/src/function/table/table_scan.cpp +1 -1
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/catalog/catalog.hpp +3 -0
- package/src/duckdb/src/include/duckdb/common/enums/aggregate_handling.hpp +2 -0
- package/src/duckdb/src/include/duckdb/common/enums/expression_type.hpp +2 -3
- package/src/duckdb/src/include/duckdb/common/enums/joinref_type.hpp +2 -0
- package/src/duckdb/src/include/duckdb/common/enums/order_type.hpp +2 -0
- package/src/duckdb/src/include/duckdb/common/enums/set_operation_type.hpp +2 -1
- package/src/duckdb/src/include/duckdb/common/exception.hpp +40 -9
- package/src/duckdb/src/include/duckdb/common/preserved_error.hpp +3 -0
- package/src/duckdb/src/include/duckdb/common/serializer/enum_serializer.hpp +113 -0
- package/src/duckdb/src/include/duckdb/common/serializer/format_deserializer.hpp +336 -0
- package/src/duckdb/src/include/duckdb/common/serializer/format_serializer.hpp +268 -0
- package/src/duckdb/src/include/duckdb/common/serializer/serialization_traits.hpp +126 -0
- package/src/duckdb/src/include/duckdb/common/string_util.hpp +12 -0
- package/src/duckdb/src/include/duckdb/common/types/value.hpp +2 -31
- package/src/duckdb/src/include/duckdb/common/types/vector.hpp +3 -0
- package/src/duckdb/src/include/duckdb/common/types.hpp +8 -2
- package/src/duckdb/src/include/duckdb/function/scalar/regexp.hpp +81 -1
- package/src/duckdb/src/include/duckdb/main/extension_entries.hpp +1 -0
- package/src/duckdb/src/include/duckdb/parser/common_table_expression_info.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/expression/between_expression.hpp +3 -0
- package/src/duckdb/src/include/duckdb/parser/expression/bound_expression.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/expression/case_expression.hpp +5 -0
- package/src/duckdb/src/include/duckdb/parser/expression/cast_expression.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/expression/collate_expression.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/expression/columnref_expression.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/expression/comparison_expression.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/expression/conjunction_expression.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/expression/constant_expression.hpp +3 -0
- package/src/duckdb/src/include/duckdb/parser/expression/default_expression.hpp +1 -0
- package/src/duckdb/src/include/duckdb/parser/expression/function_expression.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/expression/lambda_expression.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/expression/operator_expression.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/expression/parameter_expression.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/expression/positional_reference_expression.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/expression/star_expression.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/expression/subquery_expression.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/expression/window_expression.hpp +5 -0
- package/src/duckdb/src/include/duckdb/parser/parsed_data/sample_options.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/parsed_expression.hpp +5 -0
- package/src/duckdb/src/include/duckdb/parser/query_node/recursive_cte_node.hpp +3 -0
- package/src/duckdb/src/include/duckdb/parser/query_node/select_node.hpp +5 -0
- package/src/duckdb/src/include/duckdb/parser/query_node/set_operation_node.hpp +3 -0
- package/src/duckdb/src/include/duckdb/parser/query_node.hpp +11 -1
- package/src/duckdb/src/include/duckdb/parser/result_modifier.hpp +24 -1
- package/src/duckdb/src/include/duckdb/parser/sql_statement.hpp +2 -1
- package/src/duckdb/src/include/duckdb/parser/statement/select_statement.hpp +6 -1
- package/src/duckdb/src/include/duckdb/parser/tableref/basetableref.hpp +4 -0
- package/src/duckdb/src/include/duckdb/parser/tableref/emptytableref.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/tableref/expressionlistref.hpp +3 -0
- package/src/duckdb/src/include/duckdb/parser/tableref/joinref.hpp +3 -0
- package/src/duckdb/src/include/duckdb/parser/tableref/pivotref.hpp +9 -0
- package/src/duckdb/src/include/duckdb/parser/tableref/subqueryref.hpp +3 -0
- package/src/duckdb/src/include/duckdb/parser/tableref/table_function_ref.hpp +3 -0
- package/src/duckdb/src/include/duckdb/parser/tableref.hpp +3 -1
- package/src/duckdb/src/include/duckdb/storage/statistics/numeric_stats.hpp +9 -52
- package/src/duckdb/src/include/duckdb/storage/statistics/numeric_stats_union.hpp +62 -0
- package/src/duckdb/src/include/duckdb/storage/table/column_checkpoint_state.hpp +2 -1
- package/src/duckdb/src/include/duckdb/storage/table/column_data.hpp +6 -3
- package/src/duckdb/src/include/duckdb/storage/table/column_data_checkpointer.hpp +3 -2
- package/src/duckdb/src/include/duckdb/storage/table/column_segment.hpp +5 -3
- package/src/duckdb/src/include/duckdb/storage/table/persistent_table_data.hpp +4 -1
- package/src/duckdb/src/include/duckdb/storage/table/row_group.hpp +6 -3
- package/src/duckdb/src/include/duckdb/storage/table/row_group_collection.hpp +5 -3
- package/src/duckdb/src/include/duckdb/storage/table/row_group_segment_tree.hpp +37 -0
- package/src/duckdb/src/include/duckdb/storage/table/scan_state.hpp +8 -1
- package/src/duckdb/src/include/duckdb/storage/table/segment_base.hpp +4 -3
- package/src/duckdb/src/include/duckdb/storage/table/segment_tree.hpp +271 -26
- package/src/duckdb/src/main/extension/extension_install.cpp +7 -2
- package/src/duckdb/src/optimizer/deliminator.cpp +1 -1
- package/src/duckdb/src/optimizer/filter_combiner.cpp +1 -1
- package/src/duckdb/src/optimizer/join_order/join_order_optimizer.cpp +3 -3
- package/src/duckdb/src/optimizer/rule/move_constants.cpp +2 -2
- package/src/duckdb/src/optimizer/statistics/operator/propagate_filter.cpp +1 -1
- package/src/duckdb/src/parser/common_table_expression_info.cpp +19 -0
- package/src/duckdb/src/parser/expression/between_expression.cpp +17 -0
- package/src/duckdb/src/parser/expression/case_expression.cpp +28 -0
- package/src/duckdb/src/parser/expression/cast_expression.cpp +17 -0
- package/src/duckdb/src/parser/expression/collate_expression.cpp +16 -0
- package/src/duckdb/src/parser/expression/columnref_expression.cpp +15 -0
- package/src/duckdb/src/parser/expression/comparison_expression.cpp +16 -0
- package/src/duckdb/src/parser/expression/conjunction_expression.cpp +15 -0
- package/src/duckdb/src/parser/expression/constant_expression.cpp +14 -0
- package/src/duckdb/src/parser/expression/default_expression.cpp +7 -0
- package/src/duckdb/src/parser/expression/function_expression.cpp +35 -0
- package/src/duckdb/src/parser/expression/lambda_expression.cpp +16 -0
- package/src/duckdb/src/parser/expression/operator_expression.cpp +15 -0
- package/src/duckdb/src/parser/expression/parameter_expression.cpp +15 -0
- package/src/duckdb/src/parser/expression/positional_reference_expression.cpp +14 -0
- package/src/duckdb/src/parser/expression/star_expression.cpp +20 -0
- package/src/duckdb/src/parser/expression/subquery_expression.cpp +20 -0
- package/src/duckdb/src/parser/expression/window_expression.cpp +43 -0
- package/src/duckdb/src/parser/parsed_data/sample_options.cpp +22 -10
- package/src/duckdb/src/parser/parsed_expression.cpp +72 -0
- package/src/duckdb/src/parser/query_node/recursive_cte_node.cpp +21 -0
- package/src/duckdb/src/parser/query_node/select_node.cpp +31 -0
- package/src/duckdb/src/parser/query_node/set_operation_node.cpp +17 -0
- package/src/duckdb/src/parser/query_node.cpp +50 -0
- package/src/duckdb/src/parser/result_modifier.cpp +78 -0
- package/src/duckdb/src/parser/statement/select_statement.cpp +12 -0
- package/src/duckdb/src/parser/tableref/basetableref.cpp +21 -0
- package/src/duckdb/src/parser/tableref/emptytableref.cpp +4 -0
- package/src/duckdb/src/parser/tableref/expressionlistref.cpp +17 -0
- package/src/duckdb/src/parser/tableref/joinref.cpp +25 -0
- package/src/duckdb/src/parser/tableref/pivotref.cpp +53 -0
- package/src/duckdb/src/parser/tableref/subqueryref.cpp +15 -0
- package/src/duckdb/src/parser/tableref/table_function.cpp +17 -0
- package/src/duckdb/src/parser/tableref.cpp +46 -0
- package/src/duckdb/src/parser/transform/expression/transform_array_access.cpp +11 -0
- package/src/duckdb/src/parser/transform/expression/transform_bool_expr.cpp +1 -1
- package/src/duckdb/src/parser/transform/expression/transform_operator.cpp +1 -1
- package/src/duckdb/src/parser/transform/expression/transform_subquery.cpp +1 -1
- package/src/duckdb/src/planner/binder/expression/bind_function_expression.cpp +22 -4
- package/src/duckdb/src/planner/binder/expression/bind_subquery_expression.cpp +4 -0
- package/src/duckdb/src/planner/binder/tableref/plan_joinref.cpp +1 -1
- package/src/duckdb/src/planner/expression/bound_expression.cpp +4 -0
- package/src/duckdb/src/storage/checkpoint/table_data_reader.cpp +3 -11
- package/src/duckdb/src/storage/checkpoint/table_data_writer.cpp +6 -0
- package/src/duckdb/src/storage/checkpoint_manager.cpp +1 -0
- package/src/duckdb/src/storage/compression/numeric_constant.cpp +2 -2
- package/src/duckdb/src/storage/data_table.cpp +1 -1
- package/src/duckdb/src/storage/statistics/numeric_stats.cpp +145 -83
- package/src/duckdb/src/storage/statistics/numeric_stats_union.cpp +65 -0
- package/src/duckdb/src/storage/storage_info.cpp +1 -1
- package/src/duckdb/src/storage/table/column_checkpoint_state.cpp +1 -6
- package/src/duckdb/src/storage/table/column_data.cpp +29 -35
- package/src/duckdb/src/storage/table/column_data_checkpointer.cpp +5 -5
- package/src/duckdb/src/storage/table/column_segment.cpp +8 -7
- package/src/duckdb/src/storage/table/list_column_data.cpp +2 -1
- package/src/duckdb/src/storage/table/persistent_table_data.cpp +2 -1
- package/src/duckdb/src/storage/table/row_group.cpp +9 -9
- package/src/duckdb/src/storage/table/row_group_collection.cpp +82 -66
- package/src/duckdb/src/storage/table/scan_state.cpp +22 -3
- package/src/duckdb/src/storage/table/standard_column_data.cpp +1 -0
- package/src/duckdb/src/storage/table/struct_column_data.cpp +1 -0
- package/src/duckdb/src/verification/deserialized_statement_verifier.cpp +0 -1
- package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +11780 -11512
- package/src/duckdb/third_party/re2/re2/re2.cc +9 -0
- package/src/duckdb/third_party/re2/re2/re2.h +2 -0
- package/src/duckdb/ub_extension_json_json_functions.cpp +2 -0
- package/src/duckdb/ub_src_common_serializer.cpp +2 -0
- package/src/duckdb/ub_src_function_scalar_string_regexp.cpp +4 -0
- package/src/duckdb/ub_src_parser.cpp +2 -0
- package/src/duckdb/ub_src_storage_statistics.cpp +2 -0
- package/src/duckdb/ub_src_storage_table.cpp +0 -2
- package/src/utils.cpp +12 -0
- package/test/extension.test.ts +44 -26
- 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
|
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
@@ -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
|
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
|
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
|
-
|
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()) {
|