duckdb 0.7.2-dev16.0 → 0.7.2-dev225.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/package.json +1 -1
- package/src/duckdb/extension/icu/icu-extension.cpp +2 -0
- package/src/duckdb/extension/icu/icu-table-range.cpp +194 -0
- package/src/duckdb/extension/icu/include/icu-table-range.hpp +17 -0
- package/src/duckdb/extension/parquet/column_writer.cpp +0 -1
- package/src/duckdb/extension/parquet/parquet-extension.cpp +11 -2
- package/src/duckdb/src/catalog/catalog_entry/duck_schema_entry.cpp +4 -0
- package/src/duckdb/src/catalog/catalog_entry/scalar_function_catalog_entry.cpp +7 -6
- package/src/duckdb/src/catalog/catalog_entry/table_function_catalog_entry.cpp +20 -1
- package/src/duckdb/src/common/enums/statement_type.cpp +2 -0
- package/src/duckdb/src/common/types/bit.cpp +95 -58
- package/src/duckdb/src/common/types/value.cpp +149 -53
- package/src/duckdb/src/common/types/vector.cpp +13 -10
- package/src/duckdb/src/execution/operator/persistent/buffered_csv_reader.cpp +1 -1
- package/src/duckdb/src/function/aggregate/algebraic/avg.cpp +0 -6
- package/src/duckdb/src/function/aggregate/distributive/bitagg.cpp +99 -95
- package/src/duckdb/src/function/aggregate/distributive/bitstring_agg.cpp +261 -0
- package/src/duckdb/src/function/aggregate/distributive/sum.cpp +0 -3
- package/src/duckdb/src/function/aggregate/distributive_functions.cpp +1 -0
- package/src/duckdb/src/function/aggregate/sorted_aggregate_function.cpp +16 -5
- package/src/duckdb/src/function/cast/bit_cast.cpp +0 -2
- package/src/duckdb/src/function/cast/blob_cast.cpp +0 -1
- package/src/duckdb/src/function/scalar/bit/bitstring.cpp +99 -0
- package/src/duckdb/src/function/scalar/map/map_entries.cpp +61 -0
- package/src/duckdb/src/function/scalar/map/map_keys_values.cpp +97 -0
- package/src/duckdb/src/function/scalar/nested_functions.cpp +3 -0
- package/src/duckdb/src/function/scalar/operators/add.cpp +0 -9
- package/src/duckdb/src/function/scalar/operators/arithmetic.cpp +2 -14
- package/src/duckdb/src/function/scalar/operators/bitwise.cpp +0 -63
- package/src/duckdb/src/function/scalar/operators/multiply.cpp +0 -6
- package/src/duckdb/src/function/scalar/operators/subtract.cpp +0 -6
- package/src/duckdb/src/function/scalar/string_functions.cpp +1 -0
- package/src/duckdb/src/function/table/read_csv.cpp +9 -0
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/function/table_function.cpp +19 -0
- package/src/duckdb/src/include/duckdb/catalog/catalog_entry/table_function_catalog_entry.hpp +6 -8
- package/src/duckdb/src/include/duckdb/common/constants.hpp +0 -19
- package/src/duckdb/src/include/duckdb/common/enums/statement_type.hpp +2 -1
- package/src/duckdb/src/include/duckdb/common/enums/tableref_type.hpp +2 -1
- package/src/duckdb/src/include/duckdb/common/types/bit.hpp +5 -1
- package/src/duckdb/src/include/duckdb/common/types/value.hpp +2 -8
- package/src/duckdb/src/include/duckdb/common/types.hpp +1 -2
- package/src/duckdb/src/include/duckdb/function/aggregate/distributive_functions.hpp +5 -0
- package/src/duckdb/src/include/duckdb/function/scalar/bit_functions.hpp +4 -0
- package/src/duckdb/src/include/duckdb/function/scalar/nested_functions.hpp +12 -0
- package/src/duckdb/src/include/duckdb/function/table_function.hpp +2 -0
- package/src/duckdb/src/include/duckdb/main/capi/capi_internal.hpp +2 -0
- package/src/duckdb/src/include/duckdb/main/config.hpp +3 -0
- package/src/duckdb/src/include/duckdb/main/database.hpp +1 -0
- package/src/duckdb/src/include/duckdb/optimizer/join_order/cardinality_estimator.hpp +2 -2
- package/src/duckdb/src/include/duckdb/parser/common_table_expression_info.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/parsed_data/alter_info.hpp +2 -1
- package/src/duckdb/src/include/duckdb/parser/parsed_data/{alter_function_info.hpp → alter_scalar_function_info.hpp} +13 -13
- package/src/duckdb/src/include/duckdb/parser/parsed_data/alter_table_function_info.hpp +47 -0
- package/src/duckdb/src/include/duckdb/parser/parsed_data/create_table_function_info.hpp +2 -1
- package/src/duckdb/src/include/duckdb/parser/query_node.hpp +2 -1
- package/src/duckdb/src/include/duckdb/parser/statement/multi_statement.hpp +28 -0
- package/src/duckdb/src/include/duckdb/parser/tableref/list.hpp +1 -0
- package/src/duckdb/src/include/duckdb/parser/tableref/pivotref.hpp +76 -0
- package/src/duckdb/src/include/duckdb/parser/tokens.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/transformer.hpp +28 -0
- package/src/duckdb/src/include/duckdb/planner/binder.hpp +8 -0
- package/src/duckdb/src/include/duckdb/storage/buffer/block_handle.hpp +2 -0
- package/src/duckdb/src/include/duckdb/storage/buffer_manager.hpp +76 -44
- package/src/duckdb/src/include/duckdb/storage/statistics/base_statistics.hpp +2 -0
- package/src/duckdb/src/include/duckdb/storage/statistics/node_statistics.hpp +26 -0
- package/src/duckdb/src/include/duckdb/storage/table/list_column_data.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/table/scan_state.hpp +2 -0
- package/src/duckdb/src/include/duckdb.h +49 -1
- package/src/duckdb/src/include/duckdb.hpp +0 -1
- package/src/duckdb/src/main/capi/pending-c.cpp +16 -3
- package/src/duckdb/src/main/capi/result-c.cpp +27 -1
- package/src/duckdb/src/main/capi/stream-c.cpp +25 -0
- package/src/duckdb/src/main/client_context.cpp +8 -1
- package/src/duckdb/src/main/database.cpp +10 -2
- package/src/duckdb/src/optimizer/join_order/cardinality_estimator.cpp +98 -66
- package/src/duckdb/src/optimizer/join_order/join_order_optimizer.cpp +16 -3
- package/src/duckdb/src/parser/parsed_data/alter_info.cpp +7 -3
- package/src/duckdb/src/parser/parsed_data/alter_scalar_function_info.cpp +56 -0
- package/src/duckdb/src/parser/parsed_data/alter_table_function_info.cpp +51 -0
- package/src/duckdb/src/parser/parsed_data/create_scalar_function_info.cpp +3 -2
- package/src/duckdb/src/parser/parsed_data/create_table_function_info.cpp +6 -0
- package/src/duckdb/src/parser/parsed_expression_iterator.cpp +8 -0
- package/src/duckdb/src/parser/query_node.cpp +1 -1
- package/src/duckdb/src/parser/statement/multi_statement.cpp +18 -0
- package/src/duckdb/src/parser/tableref/pivotref.cpp +296 -0
- package/src/duckdb/src/parser/tableref.cpp +3 -0
- package/src/duckdb/src/parser/transform/helpers/transform_alias.cpp +12 -6
- package/src/duckdb/src/parser/transform/helpers/transform_cte.cpp +24 -0
- package/src/duckdb/src/parser/transform/statement/transform_create_function.cpp +4 -0
- package/src/duckdb/src/parser/transform/statement/transform_create_view.cpp +4 -0
- package/src/duckdb/src/parser/transform/statement/transform_pivot_stmt.cpp +150 -0
- package/src/duckdb/src/parser/transform/statement/transform_select.cpp +8 -0
- package/src/duckdb/src/parser/transform/statement/transform_select_node.cpp +1 -1
- package/src/duckdb/src/parser/transform/tableref/transform_pivot.cpp +105 -0
- package/src/duckdb/src/parser/transform/tableref/transform_tableref.cpp +2 -0
- package/src/duckdb/src/parser/transformer.cpp +15 -3
- package/src/duckdb/src/planner/binder/query_node/bind_select_node.cpp +11 -3
- package/src/duckdb/src/planner/binder/statement/bind_create.cpp +1 -1
- package/src/duckdb/src/planner/binder/statement/bind_logical_plan.cpp +17 -0
- package/src/duckdb/src/planner/binder/tableref/bind_pivot.cpp +365 -0
- package/src/duckdb/src/planner/binder.cpp +5 -0
- package/src/duckdb/src/planner/pragma_handler.cpp +10 -2
- package/src/duckdb/src/storage/buffer_manager.cpp +44 -46
- package/src/duckdb/src/storage/compression/bitpacking.cpp +25 -21
- package/src/duckdb/src/storage/compression/fixed_size_uncompressed.cpp +41 -43
- package/src/duckdb/src/storage/compression/rle.cpp +17 -13
- package/src/duckdb/src/storage/statistics/base_statistics.cpp +3 -3
- package/src/duckdb/src/storage/storage_info.cpp +1 -1
- package/src/duckdb/src/storage/table/column_data.cpp +5 -2
- package/src/duckdb/src/storage/table/list_column_data.cpp +32 -47
- package/src/duckdb/third_party/libpg_query/include/nodes/nodes.hpp +3 -0
- package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +34 -1
- package/src/duckdb/third_party/libpg_query/include/parser/gram.hpp +1016 -530
- package/src/duckdb/third_party/libpg_query/include/parser/kwlist.hpp +5 -0
- package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +22697 -21987
- package/src/duckdb/ub_src_function_aggregate_distributive.cpp +2 -0
- package/src/duckdb/ub_src_function_scalar_bit.cpp +2 -0
- package/src/duckdb/ub_src_function_scalar_map.cpp +4 -0
- package/src/duckdb/ub_src_main_capi.cpp +2 -0
- package/src/duckdb/ub_src_parser_parsed_data.cpp +4 -2
- package/src/duckdb/ub_src_parser_statement.cpp +2 -0
- package/src/duckdb/ub_src_parser_tableref.cpp +2 -0
- package/src/duckdb/ub_src_parser_transform_statement.cpp +2 -0
- package/src/duckdb/ub_src_parser_transform_tableref.cpp +2 -0
- package/src/duckdb/ub_src_planner_binder_tableref.cpp +2 -0
- package/src/duckdb/src/include/duckdb/main/loadable_extension.hpp +0 -59
- package/src/duckdb/src/parser/parsed_data/alter_function_info.cpp +0 -55
@@ -23,23 +23,75 @@ class DatabaseInstance;
|
|
23
23
|
class TemporaryDirectoryHandle;
|
24
24
|
struct EvictionQueue;
|
25
25
|
|
26
|
+
//! The BufferPool is in charge of handling memory management for one or more databases. It defines memory limits
|
27
|
+
//! and implements priority eviction among all users of the pool.
|
28
|
+
class BufferPool {
|
29
|
+
friend class BlockHandle;
|
30
|
+
friend class BlockManager;
|
31
|
+
friend class BufferManager;
|
32
|
+
|
33
|
+
public:
|
34
|
+
explicit BufferPool(idx_t maximum_memory);
|
35
|
+
virtual ~BufferPool();
|
36
|
+
|
37
|
+
//! Set a new memory limit to the buffer pool, throws an exception if the new limit is too low and not enough
|
38
|
+
//! blocks can be evicted
|
39
|
+
void SetLimit(idx_t limit, const char *exception_postscript);
|
40
|
+
|
41
|
+
idx_t GetUsedMemory() {
|
42
|
+
return current_memory;
|
43
|
+
}
|
44
|
+
idx_t GetMaxMemory() {
|
45
|
+
return maximum_memory;
|
46
|
+
}
|
47
|
+
|
48
|
+
protected:
|
49
|
+
//! Evict blocks until the currently used memory + extra_memory fit, returns false if this was not possible
|
50
|
+
//! (i.e. not enough blocks could be evicted)
|
51
|
+
//! If the "buffer" argument is specified AND the system can find a buffer to re-use for the given allocation size
|
52
|
+
//! "buffer" will be made to point to the re-usable memory. Note that this is not guaranteed.
|
53
|
+
//! Returns a pair. result.first indicates if eviction was successful. result.second contains the
|
54
|
+
//! reservation handle, which can be moved to the BlockHandle that will own the reservation.
|
55
|
+
struct EvictionResult {
|
56
|
+
bool success;
|
57
|
+
TempBufferPoolReservation reservation;
|
58
|
+
};
|
59
|
+
virtual EvictionResult EvictBlocks(idx_t extra_memory, idx_t memory_limit,
|
60
|
+
unique_ptr<FileBuffer> *buffer = nullptr);
|
61
|
+
|
62
|
+
//! Garbage collect eviction queue
|
63
|
+
void PurgeQueue();
|
64
|
+
void AddToEvictionQueue(shared_ptr<BlockHandle> &handle);
|
65
|
+
|
66
|
+
private:
|
67
|
+
//! The lock for changing the memory limit
|
68
|
+
mutex limit_lock;
|
69
|
+
//! The current amount of memory that is occupied by the buffer manager (in bytes)
|
70
|
+
atomic<idx_t> current_memory;
|
71
|
+
//! The maximum amount of memory that the buffer manager can keep (in bytes)
|
72
|
+
atomic<idx_t> maximum_memory;
|
73
|
+
//! Eviction queue
|
74
|
+
unique_ptr<EvictionQueue> queue;
|
75
|
+
//! Total number of insertions into the eviction queue. This guides the schedule for calling PurgeQueue.
|
76
|
+
atomic<uint32_t> queue_insertions;
|
77
|
+
};
|
78
|
+
|
26
79
|
struct TemporaryFileInformation {
|
27
80
|
string path;
|
28
81
|
idx_t size;
|
29
82
|
};
|
30
83
|
|
31
|
-
//! The
|
32
|
-
//!
|
33
|
-
|
34
|
-
//!
|
35
|
-
//! can be shared by many BlockManagers.
|
84
|
+
//! The BufferManager is in charge of handling memory management for a singke database. It cooperatively shares a
|
85
|
+
//! BufferPool with other BufferManagers, belonging to different databases. It hands out memory buffers that can
|
86
|
+
//! be used by the database internally, and offers configuration options specific to a database, which need not be
|
87
|
+
//! shared by the BufferPool, including whether to support swapping temp buffers to disk, and where to swap them to.
|
36
88
|
class BufferManager {
|
37
89
|
friend class BufferHandle;
|
38
90
|
friend class BlockHandle;
|
39
91
|
friend class BlockManager;
|
40
92
|
|
41
93
|
public:
|
42
|
-
BufferManager(DatabaseInstance &db, string temp_directory
|
94
|
+
BufferManager(DatabaseInstance &db, string temp_directory);
|
43
95
|
virtual ~BufferManager();
|
44
96
|
|
45
97
|
//! Registers an in-memory buffer that cannot be unloaded until it is destroyed
|
@@ -58,21 +110,17 @@ public:
|
|
58
110
|
BufferHandle Pin(shared_ptr<BlockHandle> &handle);
|
59
111
|
void Unpin(shared_ptr<BlockHandle> &handle);
|
60
112
|
|
61
|
-
//! Set a new memory limit to the buffer manager, throws an exception if the new limit is too low and not enough
|
62
|
-
//! blocks can be evicted
|
63
|
-
void SetLimit(idx_t limit = (idx_t)-1);
|
64
|
-
|
65
113
|
DUCKDB_API static BufferManager &GetBufferManager(ClientContext &context);
|
66
114
|
DUCKDB_API static BufferManager &GetBufferManager(DatabaseInstance &db);
|
67
115
|
DUCKDB_API static BufferManager &GetBufferManager(AttachedDatabase &db);
|
68
116
|
|
69
117
|
//! Returns the currently allocated memory
|
70
118
|
idx_t GetUsedMemory() {
|
71
|
-
return current_memory;
|
119
|
+
return buffer_pool.current_memory;
|
72
120
|
}
|
73
121
|
//! Returns the maximum available memory
|
74
122
|
idx_t GetMaxMemory() {
|
75
|
-
return maximum_memory;
|
123
|
+
return buffer_pool.maximum_memory;
|
76
124
|
}
|
77
125
|
|
78
126
|
//! Increases the currently allocated memory, but the actual allocation does not go through the buffer manager
|
@@ -92,6 +140,10 @@ public:
|
|
92
140
|
return db;
|
93
141
|
}
|
94
142
|
|
143
|
+
BufferPool &GetBufferPool() {
|
144
|
+
return buffer_pool;
|
145
|
+
}
|
146
|
+
|
95
147
|
static idx_t GetAllocSize(idx_t block_size) {
|
96
148
|
return AlignValue<idx_t, Storage::SECTOR_SIZE>(block_size + Storage::BLOCK_HEADER_SIZE);
|
97
149
|
}
|
@@ -103,6 +155,11 @@ public:
|
|
103
155
|
DUCKDB_API void ReserveMemory(idx_t size);
|
104
156
|
DUCKDB_API void FreeReservedMemory(idx_t size);
|
105
157
|
|
158
|
+
//! Set a new memory limit to the buffer pool, throws an exception if the new limit is too low and not enough
|
159
|
+
//! blocks can be evicted. (Sugar for calling method directly on the BufferPool.)
|
160
|
+
void SetLimit(idx_t limit = (idx_t)-1) {
|
161
|
+
buffer_pool.SetLimit(limit, InMemoryWarning());
|
162
|
+
}
|
106
163
|
//! Returns a list of all temporary files
|
107
164
|
vector<TemporaryFileInformation> GetTemporaryFiles();
|
108
165
|
|
@@ -113,25 +170,6 @@ private:
|
|
113
170
|
//! This needs to be private to prevent creating blocks without ever pinning them:
|
114
171
|
//! blocks that are never pinned are never added to the eviction queue
|
115
172
|
shared_ptr<BlockHandle> RegisterMemory(idx_t block_size, bool can_destroy);
|
116
|
-
//! Evict blocks until the currently used memory + extra_memory fit, returns false if this was not possible
|
117
|
-
//! (i.e. not enough blocks could be evicted)
|
118
|
-
//! If the "buffer" argument is specified AND the system can find a buffer to re-use for the given allocation size
|
119
|
-
//! "buffer" will be made to point to the re-usable memory. Note that this is not guaranteed.
|
120
|
-
//! Returns a pair. result.first indicates if eviction was successful. result.second contains the
|
121
|
-
//! reservation handle, which can be moved to the BlockHandle that will own the reservation.
|
122
|
-
struct EvictionResult {
|
123
|
-
bool success;
|
124
|
-
TempBufferPoolReservation reservation;
|
125
|
-
};
|
126
|
-
EvictionResult EvictBlocks(idx_t extra_memory, idx_t memory_limit, unique_ptr<FileBuffer> *buffer = nullptr);
|
127
|
-
|
128
|
-
//! Helper
|
129
|
-
template <typename... ARGS>
|
130
|
-
TempBufferPoolReservation EvictBlocksOrThrow(idx_t extra_memory, idx_t limit, unique_ptr<FileBuffer> *buffer,
|
131
|
-
ARGS...);
|
132
|
-
|
133
|
-
//! Garbage collect eviction queue
|
134
|
-
void PurgeQueue();
|
135
173
|
|
136
174
|
//! Write a temporary buffer to disk
|
137
175
|
void WriteTemporaryBuffer(block_id_t block_id, FileBuffer &buffer);
|
@@ -144,9 +182,7 @@ private:
|
|
144
182
|
|
145
183
|
void RequireTemporaryDirectory();
|
146
184
|
|
147
|
-
|
148
|
-
|
149
|
-
string InMemoryWarning();
|
185
|
+
const char *InMemoryWarning();
|
150
186
|
|
151
187
|
static data_ptr_t BufferAllocatorAllocate(PrivateAllocatorData *private_data, idx_t size);
|
152
188
|
static void BufferAllocatorFree(PrivateAllocatorData *private_data, data_ptr_t pointer, idx_t size);
|
@@ -157,27 +193,23 @@ private:
|
|
157
193
|
//! overwrites the data within with garbage. Any readers that do not hold the pin will notice
|
158
194
|
void VerifyZeroReaders(shared_ptr<BlockHandle> &handle);
|
159
195
|
|
196
|
+
//! Helper
|
197
|
+
template <typename... ARGS>
|
198
|
+
TempBufferPoolReservation EvictBlocksOrThrow(idx_t extra_memory, unique_ptr<FileBuffer> *buffer, ARGS...);
|
199
|
+
|
160
200
|
private:
|
161
201
|
//! The database instance
|
162
202
|
DatabaseInstance &db;
|
163
|
-
//! The
|
164
|
-
|
165
|
-
//! The current amount of memory that is occupied by the buffer manager (in bytes)
|
166
|
-
atomic<idx_t> current_memory;
|
167
|
-
//! The maximum amount of memory that the buffer manager can keep (in bytes)
|
168
|
-
atomic<idx_t> maximum_memory;
|
203
|
+
//! The buffer pool
|
204
|
+
BufferPool &buffer_pool;
|
169
205
|
//! The directory name where temporary files are stored
|
170
206
|
string temp_directory;
|
171
207
|
//! Lock for creating the temp handle
|
172
208
|
mutex temp_handle_lock;
|
173
209
|
//! Handle for the temporary directory
|
174
210
|
unique_ptr<TemporaryDirectoryHandle> temp_directory_handle;
|
175
|
-
//! Eviction queue
|
176
|
-
unique_ptr<EvictionQueue> queue;
|
177
211
|
//! The temporary id used for managed buffers
|
178
212
|
atomic<block_id_t> temporary_id;
|
179
|
-
//! Total number of insertions into the eviction queue. This guides the schedule for calling PurgeQueue.
|
180
|
-
atomic<uint32_t> queue_insertions;
|
181
213
|
//! Allocator associated with the buffer manager, that passes all allocations through this buffer manager
|
182
214
|
Allocator buffer_allocator;
|
183
215
|
//! Block manager for temp data
|
@@ -39,6 +39,8 @@ public:
|
|
39
39
|
unique_ptr<BaseStatistics> validity_stats;
|
40
40
|
//! The approximate count distinct stats of the column (if any)
|
41
41
|
unique_ptr<BaseStatistics> distinct_stats;
|
42
|
+
idx_t distinct_count; // estimate that one may have even if distinct_stats==nullptr
|
43
|
+
|
42
44
|
//! Whether these are 'global' stats, i.e., over a whole table, or just over a segment
|
43
45
|
//! Some statistics are more expensive to keep, therefore we only keep them globally
|
44
46
|
StatisticsType stats_type;
|
@@ -9,6 +9,7 @@
|
|
9
9
|
#pragma once
|
10
10
|
|
11
11
|
#include "duckdb/common/common.hpp"
|
12
|
+
#include "duckdb/common/serializer.hpp"
|
12
13
|
|
13
14
|
namespace duckdb {
|
14
15
|
|
@@ -23,6 +24,31 @@ public:
|
|
23
24
|
: has_estimated_cardinality(true), estimated_cardinality(estimated_cardinality), has_max_cardinality(true),
|
24
25
|
max_cardinality(max_cardinality) {
|
25
26
|
}
|
27
|
+
void Serialize(Serializer &serializer) const {
|
28
|
+
serializer.Write(has_estimated_cardinality);
|
29
|
+
if (has_estimated_cardinality) {
|
30
|
+
serializer.Write(estimated_cardinality);
|
31
|
+
serializer.Write(has_max_cardinality);
|
32
|
+
if (has_max_cardinality) {
|
33
|
+
serializer.Write(max_cardinality);
|
34
|
+
}
|
35
|
+
} else {
|
36
|
+
D_ASSERT(!has_max_cardinality);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
static unique_ptr<NodeStatistics> Deserialize(Deserializer &source) {
|
40
|
+
bool has_estimated_cardinality = source.Read<bool>();
|
41
|
+
if (!has_estimated_cardinality) {
|
42
|
+
return make_unique<NodeStatistics>();
|
43
|
+
}
|
44
|
+
idx_t estimated_cardinality = source.Read<idx_t>();
|
45
|
+
bool has_max_cardinality = source.Read<bool>();
|
46
|
+
if (!has_max_cardinality) {
|
47
|
+
return make_unique<NodeStatistics>(estimated_cardinality);
|
48
|
+
}
|
49
|
+
idx_t max_cardinality = source.Read<idx_t>();
|
50
|
+
return make_unique<NodeStatistics>(estimated_cardinality, max_cardinality);
|
51
|
+
}
|
26
52
|
|
27
53
|
//! Whether or not the node has an estimated cardinality specified
|
28
54
|
bool has_estimated_cardinality;
|
@@ -64,6 +64,8 @@ struct ColumnScanState {
|
|
64
64
|
//! We initialize one SegmentScanState per segment, however, if scanning a DataChunk requires us to scan over more
|
65
65
|
//! than one Segment, we need to keep the scan states of the previous segments around
|
66
66
|
vector<unique_ptr<SegmentScanState>> previous_states;
|
67
|
+
//! The last read offset in the child state (used for LIST columns only)
|
68
|
+
idx_t last_offset = 0;
|
67
69
|
|
68
70
|
public:
|
69
71
|
//! Move the scan state forward by "count" rows (including all child states)
|
@@ -35,7 +35,10 @@
|
|
35
35
|
#endif
|
36
36
|
#endif
|
37
37
|
|
38
|
-
//
|
38
|
+
// API versions
|
39
|
+
// if no explicit API version is defined, the latest API version is used
|
40
|
+
// Note that using older API versions (i.e. not using DUCKDB_API_LATEST) is deprecated.
|
41
|
+
// These will not be supported long-term, and will be removed in future versions.
|
39
42
|
#ifndef DUCKDB_API_0_3_1
|
40
43
|
#define DUCKDB_API_0_3_1 1
|
41
44
|
#endif
|
@@ -570,6 +573,14 @@ Use `duckdb_result_chunk_count` to figure out how many chunks there are in the r
|
|
570
573
|
*/
|
571
574
|
DUCKDB_API duckdb_data_chunk duckdb_result_get_chunk(duckdb_result result, idx_t chunk_index);
|
572
575
|
|
576
|
+
/*!
|
577
|
+
Checks if the type of the internal result is StreamQueryResult.
|
578
|
+
|
579
|
+
* result: The result object to check.
|
580
|
+
* returns: Whether or not the result object is of the type StreamQueryResult
|
581
|
+
*/
|
582
|
+
DUCKDB_API bool duckdb_result_is_streaming(duckdb_result result);
|
583
|
+
|
573
584
|
/*!
|
574
585
|
Returns the number of data chunks present in the result.
|
575
586
|
|
@@ -1106,6 +1117,21 @@ Note that after calling `duckdb_pending_prepared`, the pending result should alw
|
|
1106
1117
|
DUCKDB_API duckdb_state duckdb_pending_prepared(duckdb_prepared_statement prepared_statement,
|
1107
1118
|
duckdb_pending_result *out_result);
|
1108
1119
|
|
1120
|
+
/*!
|
1121
|
+
Executes the prepared statement with the given bound parameters, and returns a pending result.
|
1122
|
+
This pending result will create a streaming duckdb_result when executed.
|
1123
|
+
The pending result represents an intermediate structure for a query that is not yet fully executed.
|
1124
|
+
|
1125
|
+
Note that after calling `duckdb_pending_prepared_streaming`, the pending result should always be destroyed using
|
1126
|
+
`duckdb_destroy_pending`, even if this function returns DuckDBError.
|
1127
|
+
|
1128
|
+
* prepared_statement: The prepared statement to execute.
|
1129
|
+
* out_result: The pending query result.
|
1130
|
+
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.
|
1131
|
+
*/
|
1132
|
+
DUCKDB_API duckdb_state duckdb_pending_prepared_streaming(duckdb_prepared_statement prepared_statement,
|
1133
|
+
duckdb_pending_result *out_result);
|
1134
|
+
|
1109
1135
|
/*!
|
1110
1136
|
Closes the pending result and de-allocates all memory allocated for the result.
|
1111
1137
|
|
@@ -2319,6 +2345,28 @@ Returns true if execution of the current query is finished.
|
|
2319
2345
|
*/
|
2320
2346
|
DUCKDB_API bool duckdb_execution_is_finished(duckdb_connection con);
|
2321
2347
|
|
2348
|
+
//===--------------------------------------------------------------------===//
|
2349
|
+
// Streaming Result Interface
|
2350
|
+
//===--------------------------------------------------------------------===//
|
2351
|
+
|
2352
|
+
/*!
|
2353
|
+
Fetches a data chunk from the (streaming) duckdb_result. This function should be called repeatedly until the result is
|
2354
|
+
exhausted.
|
2355
|
+
|
2356
|
+
The result must be destroyed with `duckdb_destroy_data_chunk`.
|
2357
|
+
|
2358
|
+
This function can only be used on duckdb_results created with 'duckdb_pending_prepared_streaming'
|
2359
|
+
|
2360
|
+
If this function is used, none of the other result functions can be used and vice versa (i.e. this function cannot be
|
2361
|
+
mixed with the legacy result functions or the materialized result functions).
|
2362
|
+
|
2363
|
+
It is not known beforehand how many chunks will be returned by this result.
|
2364
|
+
|
2365
|
+
* result: The result object to fetch the data chunk from.
|
2366
|
+
* returns: The resulting data chunk. Returns `NULL` if the result has an error.
|
2367
|
+
*/
|
2368
|
+
DUCKDB_API duckdb_data_chunk duckdb_stream_fetch_chunk(duckdb_result result);
|
2369
|
+
|
2322
2370
|
#ifdef __cplusplus
|
2323
2371
|
}
|
2324
2372
|
#endif
|
@@ -9,14 +9,16 @@ using duckdb::PendingQueryResult;
|
|
9
9
|
using duckdb::PendingStatementWrapper;
|
10
10
|
using duckdb::PreparedStatementWrapper;
|
11
11
|
|
12
|
-
duckdb_state
|
12
|
+
duckdb_state duckdb_pending_prepared_internal(duckdb_prepared_statement prepared_statement,
|
13
|
+
duckdb_pending_result *out_result, bool allow_streaming) {
|
13
14
|
if (!prepared_statement || !out_result) {
|
14
15
|
return DuckDBError;
|
15
16
|
}
|
16
17
|
auto wrapper = (PreparedStatementWrapper *)prepared_statement;
|
17
18
|
auto result = new PendingStatementWrapper();
|
19
|
+
result->allow_streaming = allow_streaming;
|
18
20
|
try {
|
19
|
-
result->statement = wrapper->statement->PendingQuery(wrapper->values,
|
21
|
+
result->statement = wrapper->statement->PendingQuery(wrapper->values, allow_streaming);
|
20
22
|
} catch (const duckdb::Exception &ex) {
|
21
23
|
result->statement = make_unique<PendingQueryResult>(duckdb::PreservedError(ex));
|
22
24
|
} catch (std::exception &ex) {
|
@@ -28,6 +30,15 @@ duckdb_state duckdb_pending_prepared(duckdb_prepared_statement prepared_statemen
|
|
28
30
|
return return_value;
|
29
31
|
}
|
30
32
|
|
33
|
+
duckdb_state duckdb_pending_prepared(duckdb_prepared_statement prepared_statement, duckdb_pending_result *out_result) {
|
34
|
+
return duckdb_pending_prepared_internal(prepared_statement, out_result, false);
|
35
|
+
}
|
36
|
+
|
37
|
+
duckdb_state duckdb_pending_prepared_streaming(duckdb_prepared_statement prepared_statement,
|
38
|
+
duckdb_pending_result *out_result) {
|
39
|
+
return duckdb_pending_prepared_internal(prepared_statement, out_result, true);
|
40
|
+
}
|
41
|
+
|
31
42
|
void duckdb_destroy_pending(duckdb_pending_result *pending_result) {
|
32
43
|
if (!pending_result || !*pending_result) {
|
33
44
|
return;
|
@@ -90,7 +101,9 @@ duckdb_state duckdb_execute_pending(duckdb_pending_result pending_result, duckdb
|
|
90
101
|
if (!wrapper->statement) {
|
91
102
|
return DuckDBError;
|
92
103
|
}
|
93
|
-
|
104
|
+
|
105
|
+
std::unique_ptr<duckdb::QueryResult> result;
|
106
|
+
result = wrapper->statement->Execute();
|
94
107
|
wrapper->statement.reset();
|
95
108
|
return duckdb_translate_result(std::move(result), out_result);
|
96
109
|
}
|
@@ -292,6 +292,10 @@ bool deprecated_materialize_result(duckdb_result *result) {
|
|
292
292
|
// already used as a new result set
|
293
293
|
return false;
|
294
294
|
}
|
295
|
+
if (result_data->result_set_type == CAPIResultSetType::CAPI_RESULT_TYPE_STREAMING) {
|
296
|
+
// already used as a streaming result
|
297
|
+
return false;
|
298
|
+
}
|
295
299
|
// materialize as deprecated result set
|
296
300
|
result_data->result_set_type = CAPIResultSetType::CAPI_RESULT_TYPE_DEPRECATED;
|
297
301
|
auto column_count = result_data->result->ColumnCount();
|
@@ -413,6 +417,10 @@ idx_t duckdb_row_count(duckdb_result *result) {
|
|
413
417
|
return 0;
|
414
418
|
}
|
415
419
|
auto &result_data = *((duckdb::DuckDBResultData *)result->internal_data);
|
420
|
+
if (result_data.result->type == duckdb::QueryResultType::STREAM_RESULT) {
|
421
|
+
// We can't know the row count beforehand
|
422
|
+
return 0;
|
423
|
+
}
|
416
424
|
auto &materialized = (duckdb::MaterializedQueryResult &)*result_data.result;
|
417
425
|
return materialized.RowCount();
|
418
426
|
}
|
@@ -463,7 +471,10 @@ idx_t duckdb_result_chunk_count(duckdb_result result) {
|
|
463
471
|
if (result_data.result_set_type == duckdb::CAPIResultSetType::CAPI_RESULT_TYPE_DEPRECATED) {
|
464
472
|
return 0;
|
465
473
|
}
|
466
|
-
|
474
|
+
if (result_data.result->type != duckdb::QueryResultType::MATERIALIZED_RESULT) {
|
475
|
+
// Can't know beforehand how many chunks are returned.
|
476
|
+
return 0;
|
477
|
+
}
|
467
478
|
auto &materialized = (duckdb::MaterializedQueryResult &)*result_data.result;
|
468
479
|
return materialized.Collection().ChunkCount();
|
469
480
|
}
|
@@ -476,6 +487,10 @@ duckdb_data_chunk duckdb_result_get_chunk(duckdb_result result, idx_t chunk_idx)
|
|
476
487
|
if (result_data.result_set_type == duckdb::CAPIResultSetType::CAPI_RESULT_TYPE_DEPRECATED) {
|
477
488
|
return nullptr;
|
478
489
|
}
|
490
|
+
if (result_data.result->type != duckdb::QueryResultType::MATERIALIZED_RESULT) {
|
491
|
+
// This API is only supported for materialized query results
|
492
|
+
return nullptr;
|
493
|
+
}
|
479
494
|
result_data.result_set_type = duckdb::CAPIResultSetType::CAPI_RESULT_TYPE_MATERIALIZED;
|
480
495
|
auto &materialized = (duckdb::MaterializedQueryResult &)*result_data.result;
|
481
496
|
auto &collection = materialized.Collection();
|
@@ -487,3 +502,14 @@ duckdb_data_chunk duckdb_result_get_chunk(duckdb_result result, idx_t chunk_idx)
|
|
487
502
|
collection.FetchChunk(chunk_idx, *chunk);
|
488
503
|
return reinterpret_cast<duckdb_data_chunk>(chunk.release());
|
489
504
|
}
|
505
|
+
|
506
|
+
bool duckdb_result_is_streaming(duckdb_result result) {
|
507
|
+
if (!result.internal_data) {
|
508
|
+
return false;
|
509
|
+
}
|
510
|
+
if (duckdb_result_error(&result) != nullptr) {
|
511
|
+
return false;
|
512
|
+
}
|
513
|
+
auto &result_data = *((duckdb::DuckDBResultData *)result.internal_data);
|
514
|
+
return result_data.result->type == duckdb::QueryResultType::STREAM_RESULT;
|
515
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#include "duckdb/main/capi/capi_internal.hpp"
|
2
|
+
#include "duckdb/common/types/timestamp.hpp"
|
3
|
+
#include "duckdb/common/allocator.hpp"
|
4
|
+
|
5
|
+
duckdb_data_chunk duckdb_stream_fetch_chunk(duckdb_result result) {
|
6
|
+
if (!result.internal_data) {
|
7
|
+
return nullptr;
|
8
|
+
}
|
9
|
+
auto &result_data = *((duckdb::DuckDBResultData *)result.internal_data);
|
10
|
+
if (result_data.result_set_type == duckdb::CAPIResultSetType::CAPI_RESULT_TYPE_DEPRECATED) {
|
11
|
+
return nullptr;
|
12
|
+
}
|
13
|
+
if (result_data.result->type != duckdb::QueryResultType::STREAM_RESULT) {
|
14
|
+
// We can only fetch from a StreamQueryResult
|
15
|
+
return nullptr;
|
16
|
+
}
|
17
|
+
result_data.result_set_type = duckdb::CAPIResultSetType::CAPI_RESULT_TYPE_STREAMING;
|
18
|
+
auto &streaming = (duckdb::StreamQueryResult &)*result_data.result;
|
19
|
+
if (!streaming.IsOpen()) {
|
20
|
+
return nullptr;
|
21
|
+
}
|
22
|
+
// FetchRaw ? Do we care about flattening them?
|
23
|
+
auto chunk = streaming.Fetch();
|
24
|
+
return reinterpret_cast<duckdb_data_chunk>(chunk.release());
|
25
|
+
}
|
@@ -813,12 +813,14 @@ unique_ptr<QueryResult> ClientContext::Query(const string &query, bool allow_str
|
|
813
813
|
|
814
814
|
unique_ptr<QueryResult> result;
|
815
815
|
QueryResult *last_result = nullptr;
|
816
|
+
bool last_had_result = false;
|
816
817
|
for (idx_t i = 0; i < statements.size(); i++) {
|
817
818
|
auto &statement = statements[i];
|
818
819
|
bool is_last_statement = i + 1 == statements.size();
|
819
820
|
PendingQueryParameters parameters;
|
820
821
|
parameters.allow_stream_result = allow_stream_result && is_last_statement;
|
821
822
|
auto pending_query = PendingQueryInternal(*lock, std::move(statement), parameters);
|
823
|
+
auto has_result = pending_query->properties.return_type == StatementReturnType::QUERY_RESULT;
|
822
824
|
unique_ptr<QueryResult> current_result;
|
823
825
|
if (pending_query->HasError()) {
|
824
826
|
current_result = make_unique<MaterializedQueryResult>(pending_query->GetErrorObject());
|
@@ -826,12 +828,17 @@ unique_ptr<QueryResult> ClientContext::Query(const string &query, bool allow_str
|
|
826
828
|
current_result = ExecutePendingQueryInternal(*lock, *pending_query);
|
827
829
|
}
|
828
830
|
// now append the result to the list of results
|
829
|
-
if (!last_result) {
|
831
|
+
if (!last_result || !last_had_result) {
|
830
832
|
// first result of the query
|
831
833
|
result = std::move(current_result);
|
832
834
|
last_result = result.get();
|
835
|
+
last_had_result = has_result;
|
833
836
|
} else {
|
834
837
|
// later results; attach to the result chain
|
838
|
+
// but only if there is a result
|
839
|
+
if (!has_result) {
|
840
|
+
continue;
|
841
|
+
}
|
835
842
|
last_result->next = std::move(current_result);
|
836
843
|
last_result = last_result->next.get();
|
837
844
|
}
|
@@ -191,8 +191,7 @@ void DatabaseInstance::Initialize(const char *database_path, DBConfig *user_conf
|
|
191
191
|
}
|
192
192
|
|
193
193
|
db_manager = make_unique<DatabaseManager>(*this);
|
194
|
-
buffer_manager =
|
195
|
-
make_unique<BufferManager>(*this, config.options.temporary_directory, config.options.maximum_memory);
|
194
|
+
buffer_manager = make_unique<BufferManager>(*this, config.options.temporary_directory);
|
196
195
|
scheduler = make_unique<TaskScheduler>(*this);
|
197
196
|
object_cache = make_unique<ObjectCache>();
|
198
197
|
connection_manager = make_unique<ConnectionManager>();
|
@@ -271,6 +270,10 @@ BufferManager &DatabaseInstance::GetBufferManager() {
|
|
271
270
|
return *buffer_manager;
|
272
271
|
}
|
273
272
|
|
273
|
+
BufferPool &DatabaseInstance::GetBufferPool() {
|
274
|
+
return *config.buffer_pool;
|
275
|
+
}
|
276
|
+
|
274
277
|
DatabaseManager &DatabaseManager::Get(DatabaseInstance &db) {
|
275
278
|
return db.GetDatabaseManager();
|
276
279
|
}
|
@@ -340,6 +343,11 @@ void DatabaseInstance::Configure(DBConfig &new_config) {
|
|
340
343
|
if (!config.default_allocator) {
|
341
344
|
config.default_allocator = Allocator::DefaultAllocatorReference();
|
342
345
|
}
|
346
|
+
if (new_config.buffer_pool) {
|
347
|
+
config.buffer_pool = std::move(new_config.buffer_pool);
|
348
|
+
} else {
|
349
|
+
config.buffer_pool = make_shared<BufferPool>(config.options.maximum_memory);
|
350
|
+
}
|
343
351
|
}
|
344
352
|
|
345
353
|
DBConfig &DBConfig::GetConfig(ClientContext &context) {
|