duckdb 0.8.2-dev2278.0 → 0.8.2-dev2320.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 +1 -0
- package/package.json +1 -1
- package/src/duckdb/src/common/arrow/arrow_wrapper.cpp +35 -41
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/common/arrow/arrow_wrapper.hpp +5 -3
- package/src/duckdb/src/include/duckdb/common/arrow/result_arrow_wrapper.hpp +4 -0
- package/src/duckdb/src/include/duckdb/common/stack_checker.hpp +34 -0
- package/src/duckdb/src/include/duckdb/main/chunk_scan_state/query_result.hpp +29 -0
- package/src/duckdb/src/include/duckdb/main/chunk_scan_state.hpp +45 -0
- package/src/duckdb/src/include/duckdb/main/extension_entries.hpp +3 -0
- package/src/duckdb/src/include/duckdb/main/query_result.hpp +1 -14
- package/src/duckdb/src/include/duckdb/parser/transformer.hpp +3 -15
- package/src/duckdb/src/include/duckdb/planner/expression_binder.hpp +13 -1
- package/src/duckdb/src/main/chunk_scan_state/query_result.cpp +53 -0
- package/src/duckdb/src/main/chunk_scan_state.cpp +42 -0
- package/src/duckdb/src/main/query_result.cpp +0 -13
- package/src/duckdb/src/parser/transformer.cpp +2 -16
- package/src/duckdb/src/planner/binder/expression/bind_macro_expression.cpp +5 -3
- package/src/duckdb/src/planner/binder/statement/bind_create.cpp +0 -28
- package/src/duckdb/src/planner/expression_binder.cpp +20 -0
- package/src/duckdb/ub_src_main.cpp +2 -0
- package/src/duckdb/ub_src_main_chunk_scan_state.cpp +2 -0
package/binding.gyp
CHANGED
@@ -93,6 +93,7 @@
|
|
93
93
|
"src/duckdb/ub_src_main.cpp",
|
94
94
|
"src/duckdb/ub_src_main_capi.cpp",
|
95
95
|
"src/duckdb/ub_src_main_capi_cast.cpp",
|
96
|
+
"src/duckdb/ub_src_main_chunk_scan_state.cpp",
|
96
97
|
"src/duckdb/ub_src_main_extension.cpp",
|
97
98
|
"src/duckdb/ub_src_main_relation.cpp",
|
98
99
|
"src/duckdb/ub_src_main_settings.cpp",
|
package/package.json
CHANGED
@@ -9,6 +9,7 @@
|
|
9
9
|
#include "duckdb/common/arrow/result_arrow_wrapper.hpp"
|
10
10
|
#include "duckdb/common/arrow/arrow_appender.hpp"
|
11
11
|
#include "duckdb/main/query_result.hpp"
|
12
|
+
#include "duckdb/main/chunk_scan_state/query_result.hpp"
|
12
13
|
|
13
14
|
namespace duckdb {
|
14
15
|
|
@@ -99,6 +100,7 @@ int ResultArrowArrayStreamWrapper::MyStreamGetNext(struct ArrowArrayStream *stre
|
|
99
100
|
}
|
100
101
|
auto my_stream = reinterpret_cast<ResultArrowArrayStreamWrapper *>(stream->private_data);
|
101
102
|
auto &result = *my_stream->result;
|
103
|
+
auto &scan_state = *my_stream->scan_state;
|
102
104
|
if (result.HasError()) {
|
103
105
|
my_stream->last_error = result.GetErrorObject();
|
104
106
|
return -1;
|
@@ -117,7 +119,8 @@ int ResultArrowArrayStreamWrapper::MyStreamGetNext(struct ArrowArrayStream *stre
|
|
117
119
|
}
|
118
120
|
idx_t result_count;
|
119
121
|
PreservedError error;
|
120
|
-
if (!ArrowUtil::TryFetchChunk(
|
122
|
+
if (!ArrowUtil::TryFetchChunk(scan_state, result.GetArrowOptions(result), my_stream->batch_size, out, result_count,
|
123
|
+
error)) {
|
121
124
|
D_ASSERT(error);
|
122
125
|
my_stream->last_error = error;
|
123
126
|
return -1;
|
@@ -147,7 +150,7 @@ const char *ResultArrowArrayStreamWrapper::MyStreamGetLastError(struct ArrowArra
|
|
147
150
|
}
|
148
151
|
|
149
152
|
ResultArrowArrayStreamWrapper::ResultArrowArrayStreamWrapper(unique_ptr<QueryResult> result_p, idx_t batch_size_p)
|
150
|
-
: result(std::move(result_p)) {
|
153
|
+
: result(std::move(result_p)), scan_state(make_uniq<QueryResultChunkScanState>(*result)) {
|
151
154
|
//! We first initialize the private data of the stream
|
152
155
|
stream.private_data = this;
|
153
156
|
//! Ceil Approx_Batch_Size/STANDARD_VECTOR_SIZE
|
@@ -162,52 +165,43 @@ ResultArrowArrayStreamWrapper::ResultArrowArrayStreamWrapper(unique_ptr<QueryRes
|
|
162
165
|
stream.get_last_error = ResultArrowArrayStreamWrapper::MyStreamGetLastError;
|
163
166
|
}
|
164
167
|
|
165
|
-
bool ArrowUtil::
|
166
|
-
|
167
|
-
auto &stream_result = result.Cast<StreamQueryResult>();
|
168
|
-
if (!stream_result.IsOpen()) {
|
169
|
-
return true;
|
170
|
-
}
|
171
|
-
}
|
172
|
-
return result.TryFetch(chunk, error);
|
173
|
-
}
|
174
|
-
|
175
|
-
bool ArrowUtil::TryFetchChunk(QueryResult *result, idx_t chunk_size, ArrowArray *out, idx_t &count,
|
176
|
-
PreservedError &error) {
|
168
|
+
bool ArrowUtil::TryFetchChunk(ChunkScanState &scan_state, ArrowOptions options, idx_t batch_size, ArrowArray *out,
|
169
|
+
idx_t &count, PreservedError &error) {
|
177
170
|
count = 0;
|
178
|
-
ArrowAppender appender(
|
179
|
-
auto
|
180
|
-
if (
|
171
|
+
ArrowAppender appender(scan_state.Types(), batch_size, std::move(options));
|
172
|
+
auto remaining_tuples_in_chunk = scan_state.RemainingInChunk();
|
173
|
+
if (remaining_tuples_in_chunk) {
|
181
174
|
// We start by scanning the non-finished current chunk
|
182
|
-
|
183
|
-
idx_t cur_consumption = MinValue<idx_t>(current_chunk.RemainingSize(), chunk_size);
|
175
|
+
idx_t cur_consumption = MinValue(remaining_tuples_in_chunk, batch_size);
|
184
176
|
count += cur_consumption;
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
if (!
|
192
|
-
if (
|
193
|
-
error =
|
177
|
+
auto ¤t_chunk = scan_state.CurrentChunk();
|
178
|
+
appender.Append(current_chunk, scan_state.CurrentOffset(), scan_state.CurrentOffset() + cur_consumption,
|
179
|
+
current_chunk.size());
|
180
|
+
scan_state.IncreaseOffset(cur_consumption);
|
181
|
+
}
|
182
|
+
while (count < batch_size) {
|
183
|
+
if (!scan_state.LoadNextChunk(error)) {
|
184
|
+
if (scan_state.HasError()) {
|
185
|
+
error = scan_state.GetError();
|
194
186
|
}
|
195
187
|
return false;
|
196
188
|
}
|
197
|
-
if (
|
189
|
+
if (scan_state.ChunkIsEmpty()) {
|
190
|
+
// The scan was successful, but an empty chunk was returned
|
198
191
|
break;
|
199
192
|
}
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
appender.Append(*data_chunk, 0, available_space, data_chunk->size());
|
204
|
-
count += available_space;
|
205
|
-
current_chunk.data_chunk = std::move(data_chunk);
|
206
|
-
current_chunk.position = available_space;
|
207
|
-
} else {
|
208
|
-
count += data_chunk->size();
|
209
|
-
appender.Append(*data_chunk, 0, data_chunk->size(), data_chunk->size());
|
193
|
+
auto ¤t_chunk = scan_state.CurrentChunk();
|
194
|
+
if (scan_state.Finished() || current_chunk.size() == 0) {
|
195
|
+
break;
|
210
196
|
}
|
197
|
+
// The amount we still need to append into this chunk
|
198
|
+
auto remaining = batch_size - count;
|
199
|
+
|
200
|
+
// The amount remaining, capped by the amount left in the current chunk
|
201
|
+
auto to_append_to_batch = MinValue(remaining, scan_state.RemainingInChunk());
|
202
|
+
appender.Append(current_chunk, 0, to_append_to_batch, current_chunk.size());
|
203
|
+
count += to_append_to_batch;
|
204
|
+
scan_state.IncreaseOffset(to_append_to_batch);
|
211
205
|
}
|
212
206
|
if (count > 0) {
|
213
207
|
*out = appender.Finalize();
|
@@ -215,10 +209,10 @@ bool ArrowUtil::TryFetchChunk(QueryResult *result, idx_t chunk_size, ArrowArray
|
|
215
209
|
return true;
|
216
210
|
}
|
217
211
|
|
218
|
-
idx_t ArrowUtil::FetchChunk(
|
212
|
+
idx_t ArrowUtil::FetchChunk(ChunkScanState &scan_state, ArrowOptions options, idx_t chunk_size, ArrowArray *out) {
|
219
213
|
PreservedError error;
|
220
214
|
idx_t result_count;
|
221
|
-
if (!TryFetchChunk(
|
215
|
+
if (!TryFetchChunk(scan_state, std::move(options), chunk_size, out, result_count, error)) {
|
222
216
|
error.Throw();
|
223
217
|
}
|
224
218
|
return result_count;
|
@@ -1,8 +1,8 @@
|
|
1
1
|
#ifndef DUCKDB_VERSION
|
2
|
-
#define DUCKDB_VERSION "0.8.2-
|
2
|
+
#define DUCKDB_VERSION "0.8.2-dev2320"
|
3
3
|
#endif
|
4
4
|
#ifndef DUCKDB_SOURCE_ID
|
5
|
-
#define DUCKDB_SOURCE_ID "
|
5
|
+
#define DUCKDB_SOURCE_ID "02412e1015"
|
6
6
|
#endif
|
7
7
|
#include "duckdb/function/table/system_functions.hpp"
|
8
8
|
#include "duckdb/main/database.hpp"
|
@@ -10,6 +10,8 @@
|
|
10
10
|
#include "duckdb/common/arrow/arrow.hpp"
|
11
11
|
#include "duckdb/common/helper.hpp"
|
12
12
|
#include "duckdb/common/preserved_error.hpp"
|
13
|
+
#include "duckdb/main/chunk_scan_state.hpp"
|
14
|
+
#include "duckdb/common/arrow/arrow_options.hpp"
|
13
15
|
|
14
16
|
//! Here we have the internal duckdb classes that interact with Arrow's Internal Header (i.e., duckdb/commons/arrow.hpp)
|
15
17
|
namespace duckdb {
|
@@ -56,9 +58,9 @@ public:
|
|
56
58
|
|
57
59
|
class ArrowUtil {
|
58
60
|
public:
|
59
|
-
static bool TryFetchChunk(
|
60
|
-
PreservedError &error);
|
61
|
-
static idx_t FetchChunk(
|
61
|
+
static bool TryFetchChunk(ChunkScanState &scan_state, ArrowOptions options, idx_t chunk_size, ArrowArray *out,
|
62
|
+
idx_t &result_count, PreservedError &error);
|
63
|
+
static idx_t FetchChunk(ChunkScanState &scan_state, ArrowOptions options, idx_t chunk_size, ArrowArray *out);
|
62
64
|
|
63
65
|
private:
|
64
66
|
static bool TryFetchNext(QueryResult &result, unique_ptr<DataChunk> &out, PreservedError &error);
|
@@ -10,17 +10,21 @@
|
|
10
10
|
|
11
11
|
#include "duckdb/main/query_result.hpp"
|
12
12
|
#include "duckdb/common/arrow/arrow_wrapper.hpp"
|
13
|
+
#include "duckdb/main/chunk_scan_state.hpp"
|
13
14
|
|
14
15
|
namespace duckdb {
|
15
16
|
class ResultArrowArrayStreamWrapper {
|
16
17
|
public:
|
17
18
|
explicit ResultArrowArrayStreamWrapper(unique_ptr<QueryResult> result, idx_t batch_size);
|
19
|
+
|
20
|
+
public:
|
18
21
|
ArrowArrayStream stream;
|
19
22
|
unique_ptr<QueryResult> result;
|
20
23
|
PreservedError last_error;
|
21
24
|
idx_t batch_size;
|
22
25
|
vector<LogicalType> column_types;
|
23
26
|
vector<string> column_names;
|
27
|
+
unique_ptr<ChunkScanState> scan_state;
|
24
28
|
|
25
29
|
private:
|
26
30
|
static int MyStreamGetSchema(struct ArrowArrayStream *stream, struct ArrowSchema *out);
|
@@ -0,0 +1,34 @@
|
|
1
|
+
//===----------------------------------------------------------------------===//
|
2
|
+
// DuckDB
|
3
|
+
//
|
4
|
+
// duckdb/common/stack_checker.hpp
|
5
|
+
//
|
6
|
+
//
|
7
|
+
//===----------------------------------------------------------------------===//
|
8
|
+
|
9
|
+
#pragma once
|
10
|
+
|
11
|
+
namespace duckdb {
|
12
|
+
|
13
|
+
template <class RECURSIVE_CLASS>
|
14
|
+
class StackChecker {
|
15
|
+
public:
|
16
|
+
StackChecker(RECURSIVE_CLASS &recursive_class_p, idx_t stack_usage_p)
|
17
|
+
: recursive_class(recursive_class_p), stack_usage(stack_usage_p) {
|
18
|
+
recursive_class.stack_depth += stack_usage;
|
19
|
+
}
|
20
|
+
~StackChecker() {
|
21
|
+
recursive_class.stack_depth -= stack_usage;
|
22
|
+
}
|
23
|
+
StackChecker(StackChecker &&other) noexcept
|
24
|
+
: recursive_class(other.recursive_class), stack_usage(other.stack_usage) {
|
25
|
+
other.stack_usage = 0;
|
26
|
+
}
|
27
|
+
StackChecker(const StackChecker &) = delete;
|
28
|
+
|
29
|
+
private:
|
30
|
+
RECURSIVE_CLASS &recursive_class;
|
31
|
+
idx_t stack_usage;
|
32
|
+
};
|
33
|
+
|
34
|
+
} // namespace duckdb
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "duckdb/main/chunk_scan_state.hpp"
|
4
|
+
#include "duckdb/common/preserved_error.hpp"
|
5
|
+
|
6
|
+
namespace duckdb {
|
7
|
+
|
8
|
+
class QueryResult;
|
9
|
+
|
10
|
+
class QueryResultChunkScanState : public ChunkScanState {
|
11
|
+
public:
|
12
|
+
QueryResultChunkScanState(QueryResult &result);
|
13
|
+
~QueryResultChunkScanState();
|
14
|
+
|
15
|
+
public:
|
16
|
+
bool LoadNextChunk(PreservedError &error) override;
|
17
|
+
bool HasError() const override;
|
18
|
+
PreservedError &GetError() override;
|
19
|
+
const vector<LogicalType> &Types() const override;
|
20
|
+
const vector<string> &Names() const override;
|
21
|
+
|
22
|
+
private:
|
23
|
+
bool InternalLoad(PreservedError &error);
|
24
|
+
|
25
|
+
private:
|
26
|
+
QueryResult &result;
|
27
|
+
};
|
28
|
+
|
29
|
+
} // namespace duckdb
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "duckdb/common/vector.hpp"
|
4
|
+
#include "duckdb/common/unique_ptr.hpp"
|
5
|
+
#include "duckdb/common/preserved_error.hpp"
|
6
|
+
|
7
|
+
namespace duckdb {
|
8
|
+
|
9
|
+
class DataChunk;
|
10
|
+
|
11
|
+
//! Abstract chunk fetcher
|
12
|
+
class ChunkScanState {
|
13
|
+
public:
|
14
|
+
explicit ChunkScanState() {
|
15
|
+
}
|
16
|
+
virtual ~ChunkScanState() {
|
17
|
+
}
|
18
|
+
|
19
|
+
public:
|
20
|
+
ChunkScanState(const ChunkScanState &other) = delete;
|
21
|
+
ChunkScanState(ChunkScanState &&other) = default;
|
22
|
+
ChunkScanState &operator=(const ChunkScanState &other) = delete;
|
23
|
+
ChunkScanState &operator=(ChunkScanState &&other) = default;
|
24
|
+
|
25
|
+
public:
|
26
|
+
virtual bool LoadNextChunk(PreservedError &error) = 0;
|
27
|
+
virtual bool HasError() const = 0;
|
28
|
+
virtual PreservedError &GetError() = 0;
|
29
|
+
virtual const vector<LogicalType> &Types() const = 0;
|
30
|
+
virtual const vector<string> &Names() const = 0;
|
31
|
+
idx_t CurrentOffset() const;
|
32
|
+
idx_t RemainingInChunk() const;
|
33
|
+
DataChunk &CurrentChunk();
|
34
|
+
bool ChunkIsEmpty() const;
|
35
|
+
bool Finished() const;
|
36
|
+
bool ScanStarted() const;
|
37
|
+
void IncreaseOffset(idx_t increment, bool unsafe = false);
|
38
|
+
|
39
|
+
protected:
|
40
|
+
idx_t offset = 0;
|
41
|
+
bool finished = false;
|
42
|
+
unique_ptr<DataChunk> current_chunk;
|
43
|
+
};
|
44
|
+
|
45
|
+
} // namespace duckdb
|
@@ -162,6 +162,9 @@ static constexpr ExtensionEntry EXTENSION_FUNCTIONS[] = {{"->>", "json"},
|
|
162
162
|
{"st_removerepeatedpoints", "spatial"},
|
163
163
|
{"st_geomfromgeojson", "spatial"},
|
164
164
|
{"st_readosm", "spatial"},
|
165
|
+
{"st_reduceprecision", "spatial"},
|
166
|
+
{"st_geomfromhexwkb", "spatial"},
|
167
|
+
{"st_geomfromhexewkb", "spatial"},
|
165
168
|
{"st_numpoints", "spatial"}};
|
166
169
|
|
167
170
|
static constexpr ExtensionEntry EXTENSION_SETTINGS[] = {
|
@@ -63,16 +63,7 @@ protected:
|
|
63
63
|
//! The error (in case execution was not successful)
|
64
64
|
PreservedError error;
|
65
65
|
};
|
66
|
-
|
67
|
-
//! The current data chunk
|
68
|
-
unique_ptr<DataChunk> data_chunk;
|
69
|
-
//! The current position in the data chunk
|
70
|
-
idx_t position;
|
71
|
-
//! If we have a current chunk we must scan for result production
|
72
|
-
bool Valid();
|
73
|
-
//! The remaining size of the current chunk
|
74
|
-
idx_t RemainingSize();
|
75
|
-
};
|
66
|
+
|
76
67
|
//! The QueryResult object holds the result of a query. It can either be a MaterializedQueryResult, in which case the
|
77
68
|
//! result contains the entire result set, or a StreamQueryResult in which case the Fetch method can be called to
|
78
69
|
//! incrementally fetch data from the database.
|
@@ -89,10 +80,6 @@ public:
|
|
89
80
|
ClientProperties client_properties;
|
90
81
|
//! The next result (if any)
|
91
82
|
unique_ptr<QueryResult> next;
|
92
|
-
//! In case we are converting the result from Native DuckDB to a different library (e.g., Arrow, Polars)
|
93
|
-
//! We might be producing chunks of a pre-determined size.
|
94
|
-
//! To comply, we use the following variable to store the current chunk, and it's position.
|
95
|
-
CurrentChunk current_chunk;
|
96
83
|
|
97
84
|
public:
|
98
85
|
template <class TARGET>
|
@@ -11,6 +11,7 @@
|
|
11
11
|
#include "duckdb/common/case_insensitive_map.hpp"
|
12
12
|
#include "duckdb/common/constants.hpp"
|
13
13
|
#include "duckdb/common/enums/expression_type.hpp"
|
14
|
+
#include "duckdb/common/stack_checker.hpp"
|
14
15
|
#include "duckdb/common/types.hpp"
|
15
16
|
#include "duckdb/common/unordered_map.hpp"
|
16
17
|
#include "duckdb/parser/group_by_node.hpp"
|
@@ -26,7 +27,6 @@
|
|
26
27
|
namespace duckdb {
|
27
28
|
|
28
29
|
class ColumnDefinition;
|
29
|
-
class StackChecker;
|
30
30
|
struct OrderByNode;
|
31
31
|
struct CopyInfo;
|
32
32
|
struct CommonTableExpressionInfo;
|
@@ -39,7 +39,7 @@ struct PivotColumn;
|
|
39
39
|
//! The transformer class is responsible for transforming the internal Postgres
|
40
40
|
//! parser representation into the DuckDB representation
|
41
41
|
class Transformer {
|
42
|
-
friend class StackChecker
|
42
|
+
friend class StackChecker<Transformer>;
|
43
43
|
|
44
44
|
struct CreatePivotEntry {
|
45
45
|
string enum_name;
|
@@ -343,7 +343,7 @@ private:
|
|
343
343
|
idx_t stack_depth;
|
344
344
|
|
345
345
|
void InitializeStackCheck();
|
346
|
-
StackChecker StackCheck(idx_t extra_stack = 1);
|
346
|
+
StackChecker<Transformer> StackCheck(idx_t extra_stack = 1);
|
347
347
|
|
348
348
|
public:
|
349
349
|
template <class T>
|
@@ -356,18 +356,6 @@ public:
|
|
356
356
|
}
|
357
357
|
};
|
358
358
|
|
359
|
-
class StackChecker {
|
360
|
-
public:
|
361
|
-
StackChecker(Transformer &transformer, idx_t stack_usage);
|
362
|
-
~StackChecker();
|
363
|
-
StackChecker(StackChecker &&) noexcept;
|
364
|
-
StackChecker(const StackChecker &) = delete;
|
365
|
-
|
366
|
-
private:
|
367
|
-
Transformer &transformer;
|
368
|
-
idx_t stack_usage;
|
369
|
-
};
|
370
|
-
|
371
359
|
vector<string> ReadPgListToString(duckdb_libpgquery::PGList *column_list);
|
372
360
|
|
373
361
|
} // namespace duckdb
|
@@ -9,11 +9,12 @@
|
|
9
9
|
#pragma once
|
10
10
|
|
11
11
|
#include "duckdb/common/exception.hpp"
|
12
|
+
#include "duckdb/common/stack_checker.hpp"
|
13
|
+
#include "duckdb/common/unordered_map.hpp"
|
12
14
|
#include "duckdb/parser/expression/bound_expression.hpp"
|
13
15
|
#include "duckdb/parser/parsed_expression.hpp"
|
14
16
|
#include "duckdb/parser/tokens.hpp"
|
15
17
|
#include "duckdb/planner/expression.hpp"
|
16
|
-
#include "duckdb/common/unordered_map.hpp"
|
17
18
|
|
18
19
|
namespace duckdb {
|
19
20
|
|
@@ -51,6 +52,8 @@ struct BindResult {
|
|
51
52
|
};
|
52
53
|
|
53
54
|
class ExpressionBinder {
|
55
|
+
friend class StackChecker<ExpressionBinder>;
|
56
|
+
|
54
57
|
public:
|
55
58
|
ExpressionBinder(Binder &binder, ClientContext &context, bool replace_binder = false);
|
56
59
|
virtual ~ExpressionBinder();
|
@@ -110,6 +113,15 @@ public:
|
|
110
113
|
|
111
114
|
void ReplaceMacroParametersRecursive(unique_ptr<ParsedExpression> &expr);
|
112
115
|
|
116
|
+
private:
|
117
|
+
//! Maximum stack depth
|
118
|
+
static constexpr const idx_t MAXIMUM_STACK_DEPTH = 128;
|
119
|
+
//! Current stack depth
|
120
|
+
idx_t stack_depth = DConstants::INVALID_INDEX;
|
121
|
+
|
122
|
+
void InitializeStackCheck();
|
123
|
+
StackChecker<ExpressionBinder> StackCheck(const ParsedExpression &expr, idx_t extra_stack = 1);
|
124
|
+
|
113
125
|
protected:
|
114
126
|
BindResult BindExpression(BetweenExpression &expr, idx_t depth);
|
115
127
|
BindResult BindExpression(CaseExpression &expr, idx_t depth);
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#include "duckdb/main/query_result.hpp"
|
2
|
+
#include "duckdb/main/stream_query_result.hpp"
|
3
|
+
#include "duckdb/main/chunk_scan_state/query_result.hpp"
|
4
|
+
|
5
|
+
namespace duckdb {
|
6
|
+
|
7
|
+
QueryResultChunkScanState::QueryResultChunkScanState(QueryResult &result) : ChunkScanState(), result(result) {
|
8
|
+
}
|
9
|
+
|
10
|
+
QueryResultChunkScanState::~QueryResultChunkScanState() {
|
11
|
+
}
|
12
|
+
|
13
|
+
bool QueryResultChunkScanState::InternalLoad(PreservedError &error) {
|
14
|
+
D_ASSERT(!finished);
|
15
|
+
if (result.type == QueryResultType::STREAM_RESULT) {
|
16
|
+
auto &stream_result = result.Cast<StreamQueryResult>();
|
17
|
+
if (!stream_result.IsOpen()) {
|
18
|
+
return true;
|
19
|
+
}
|
20
|
+
}
|
21
|
+
return result.TryFetch(current_chunk, error);
|
22
|
+
}
|
23
|
+
|
24
|
+
bool QueryResultChunkScanState::HasError() const {
|
25
|
+
return result.HasError();
|
26
|
+
}
|
27
|
+
|
28
|
+
PreservedError &QueryResultChunkScanState::GetError() {
|
29
|
+
D_ASSERT(result.HasError());
|
30
|
+
return result.GetErrorObject();
|
31
|
+
}
|
32
|
+
|
33
|
+
const vector<LogicalType> &QueryResultChunkScanState::Types() const {
|
34
|
+
return result.types;
|
35
|
+
}
|
36
|
+
|
37
|
+
const vector<string> &QueryResultChunkScanState::Names() const {
|
38
|
+
return result.names;
|
39
|
+
}
|
40
|
+
|
41
|
+
bool QueryResultChunkScanState::LoadNextChunk(PreservedError &error) {
|
42
|
+
if (finished) {
|
43
|
+
return !finished;
|
44
|
+
}
|
45
|
+
auto load_result = InternalLoad(error);
|
46
|
+
if (!load_result) {
|
47
|
+
finished = true;
|
48
|
+
}
|
49
|
+
offset = 0;
|
50
|
+
return !finished;
|
51
|
+
}
|
52
|
+
|
53
|
+
} // namespace duckdb
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#include "duckdb/common/types/data_chunk.hpp"
|
2
|
+
#include "duckdb/main/chunk_scan_state.hpp"
|
3
|
+
|
4
|
+
namespace duckdb {
|
5
|
+
|
6
|
+
idx_t ChunkScanState::CurrentOffset() const {
|
7
|
+
return offset;
|
8
|
+
}
|
9
|
+
|
10
|
+
void ChunkScanState::IncreaseOffset(idx_t increment, bool unsafe) {
|
11
|
+
D_ASSERT(unsafe || increment <= RemainingInChunk());
|
12
|
+
offset += increment;
|
13
|
+
}
|
14
|
+
|
15
|
+
bool ChunkScanState::ChunkIsEmpty() const {
|
16
|
+
return !current_chunk || current_chunk->size() == 0;
|
17
|
+
}
|
18
|
+
|
19
|
+
bool ChunkScanState::Finished() const {
|
20
|
+
return finished;
|
21
|
+
}
|
22
|
+
|
23
|
+
bool ChunkScanState::ScanStarted() const {
|
24
|
+
return !ChunkIsEmpty();
|
25
|
+
}
|
26
|
+
|
27
|
+
DataChunk &ChunkScanState::CurrentChunk() {
|
28
|
+
// Scan must already be started
|
29
|
+
D_ASSERT(current_chunk);
|
30
|
+
return *current_chunk;
|
31
|
+
}
|
32
|
+
|
33
|
+
idx_t ChunkScanState::RemainingInChunk() const {
|
34
|
+
if (ChunkIsEmpty()) {
|
35
|
+
return 0;
|
36
|
+
}
|
37
|
+
D_ASSERT(current_chunk);
|
38
|
+
D_ASSERT(offset <= current_chunk->size());
|
39
|
+
return current_chunk->size() - offset;
|
40
|
+
}
|
41
|
+
|
42
|
+
} // namespace duckdb
|
@@ -57,19 +57,6 @@ QueryResult::QueryResult(QueryResultType type, StatementType statement_type, Sta
|
|
57
57
|
client_properties(std::move(client_properties_p)) {
|
58
58
|
}
|
59
59
|
|
60
|
-
bool CurrentChunk::Valid() {
|
61
|
-
if (data_chunk) {
|
62
|
-
if (position < data_chunk->size()) {
|
63
|
-
return true;
|
64
|
-
}
|
65
|
-
}
|
66
|
-
return false;
|
67
|
-
}
|
68
|
-
|
69
|
-
idx_t CurrentChunk::RemainingSize() {
|
70
|
-
return data_chunk->size() - position;
|
71
|
-
}
|
72
|
-
|
73
60
|
QueryResult::QueryResult(QueryResultType type, PreservedError error)
|
74
61
|
: BaseQueryResult(type, std::move(error)), client_properties("UTC", ArrowOffsetSize::REGULAR) {
|
75
62
|
}
|
@@ -9,20 +9,6 @@
|
|
9
9
|
|
10
10
|
namespace duckdb {
|
11
11
|
|
12
|
-
StackChecker::StackChecker(Transformer &transformer_p, idx_t stack_usage_p)
|
13
|
-
: transformer(transformer_p), stack_usage(stack_usage_p) {
|
14
|
-
transformer.stack_depth += stack_usage;
|
15
|
-
}
|
16
|
-
|
17
|
-
StackChecker::~StackChecker() {
|
18
|
-
transformer.stack_depth -= stack_usage;
|
19
|
-
}
|
20
|
-
|
21
|
-
StackChecker::StackChecker(StackChecker &&other) noexcept
|
22
|
-
: transformer(other.transformer), stack_usage(other.stack_usage) {
|
23
|
-
other.stack_usage = 0;
|
24
|
-
}
|
25
|
-
|
26
12
|
Transformer::Transformer(ParserOptions &options)
|
27
13
|
: parent(nullptr), options(options), stack_depth(DConstants::INVALID_INDEX) {
|
28
14
|
}
|
@@ -59,7 +45,7 @@ void Transformer::InitializeStackCheck() {
|
|
59
45
|
stack_depth = 0;
|
60
46
|
}
|
61
47
|
|
62
|
-
StackChecker Transformer::StackCheck(idx_t extra_stack) {
|
48
|
+
StackChecker<Transformer> Transformer::StackCheck(idx_t extra_stack) {
|
63
49
|
auto &root = RootTransformer();
|
64
50
|
D_ASSERT(root.stack_depth != DConstants::INVALID_INDEX);
|
65
51
|
if (root.stack_depth + extra_stack >= options.max_expression_depth) {
|
@@ -67,7 +53,7 @@ StackChecker Transformer::StackCheck(idx_t extra_stack) {
|
|
67
53
|
"increase the maximum expression depth.",
|
68
54
|
options.max_expression_depth);
|
69
55
|
}
|
70
|
-
return StackChecker(root, extra_stack);
|
56
|
+
return StackChecker<Transformer>(root, extra_stack);
|
71
57
|
}
|
72
58
|
|
73
59
|
unique_ptr<SQLStatement> Transformer::TransformStatement(duckdb_libpgquery::PGNode &stmt) {
|
@@ -1,12 +1,12 @@
|
|
1
1
|
#include "duckdb/catalog/catalog_entry/scalar_macro_catalog_entry.hpp"
|
2
|
+
#include "duckdb/common/reference_map.hpp"
|
2
3
|
#include "duckdb/common/string_util.hpp"
|
4
|
+
#include "duckdb/function/scalar_macro_function.hpp"
|
3
5
|
#include "duckdb/parser/expression/function_expression.hpp"
|
4
6
|
#include "duckdb/parser/expression/subquery_expression.hpp"
|
5
7
|
#include "duckdb/parser/parsed_expression_iterator.hpp"
|
6
8
|
#include "duckdb/planner/expression_binder.hpp"
|
7
9
|
|
8
|
-
#include "duckdb/function/scalar_macro_function.hpp"
|
9
|
-
|
10
10
|
namespace duckdb {
|
11
11
|
|
12
12
|
void ExpressionBinder::ReplaceMacroParametersRecursive(unique_ptr<ParsedExpression> &expr) {
|
@@ -79,8 +79,10 @@ BindResult ExpressionBinder::BindMacro(FunctionExpression &function, ScalarMacro
|
|
79
79
|
new_macro_binding->arguments = &positionals;
|
80
80
|
macro_binding = new_macro_binding.get();
|
81
81
|
|
82
|
-
// replace current expression with stored macro expression
|
82
|
+
// replace current expression with stored macro expression
|
83
83
|
expr = macro_def.expression->Copy();
|
84
|
+
|
85
|
+
// now replace the parameters
|
84
86
|
ReplaceMacroParametersRecursive(expr);
|
85
87
|
|
86
88
|
// bind the unfolded macro
|
@@ -134,33 +134,6 @@ void Binder::BindCreateViewInfo(CreateViewInfo &base) {
|
|
134
134
|
base.types = query_node.types;
|
135
135
|
}
|
136
136
|
|
137
|
-
static void QualifyFunctionNames(ClientContext &context, unique_ptr<ParsedExpression> &expr) {
|
138
|
-
switch (expr->GetExpressionClass()) {
|
139
|
-
case ExpressionClass::FUNCTION: {
|
140
|
-
auto &func = expr->Cast<FunctionExpression>();
|
141
|
-
auto function = Catalog::GetEntry(context, CatalogType::SCALAR_FUNCTION_ENTRY, func.catalog, func.schema,
|
142
|
-
func.function_name, OnEntryNotFound::RETURN_NULL);
|
143
|
-
if (function) {
|
144
|
-
func.catalog = function->ParentCatalog().GetName();
|
145
|
-
func.schema = function->ParentSchema().name;
|
146
|
-
}
|
147
|
-
break;
|
148
|
-
}
|
149
|
-
case ExpressionClass::SUBQUERY: {
|
150
|
-
// replacing parameters within a subquery is slightly different
|
151
|
-
auto &sq = (expr->Cast<SubqueryExpression>()).subquery;
|
152
|
-
ParsedExpressionIterator::EnumerateQueryNodeChildren(
|
153
|
-
*sq->node, [&](unique_ptr<ParsedExpression> &child) { QualifyFunctionNames(context, child); });
|
154
|
-
break;
|
155
|
-
}
|
156
|
-
default: // fall through
|
157
|
-
break;
|
158
|
-
}
|
159
|
-
// unfold child expressions
|
160
|
-
ParsedExpressionIterator::EnumerateChildren(
|
161
|
-
*expr, [&](unique_ptr<ParsedExpression> &child) { QualifyFunctionNames(context, child); });
|
162
|
-
}
|
163
|
-
|
164
137
|
SchemaCatalogEntry &Binder::BindCreateFunctionInfo(CreateInfo &info) {
|
165
138
|
auto &base = info.Cast<CreateMacroInfo>();
|
166
139
|
auto &scalar_function = base.function->Cast<ScalarMacroFunction>();
|
@@ -190,7 +163,6 @@ SchemaCatalogEntry &Binder::BindCreateFunctionInfo(CreateInfo &info) {
|
|
190
163
|
auto this_macro_binding = make_uniq<DummyBinding>(dummy_types, dummy_names, base.name);
|
191
164
|
macro_binding = this_macro_binding.get();
|
192
165
|
ExpressionBinder::QualifyColumnNames(*this, scalar_function.expression);
|
193
|
-
QualifyFunctionNames(context, scalar_function.expression);
|
194
166
|
|
195
167
|
// create a copy of the expression because we do not want to alter the original
|
196
168
|
auto expression = scalar_function.expression->Copy();
|
@@ -10,6 +10,7 @@ namespace duckdb {
|
|
10
10
|
|
11
11
|
ExpressionBinder::ExpressionBinder(Binder &binder, ClientContext &context, bool replace_binder)
|
12
12
|
: binder(binder), context(context) {
|
13
|
+
InitializeStackCheck();
|
13
14
|
if (replace_binder) {
|
14
15
|
stored_binder = &binder.GetActiveBinder();
|
15
16
|
binder.SetActiveBinder(*this);
|
@@ -28,7 +29,26 @@ ExpressionBinder::~ExpressionBinder() {
|
|
28
29
|
}
|
29
30
|
}
|
30
31
|
|
32
|
+
void ExpressionBinder::InitializeStackCheck() {
|
33
|
+
if (binder.HasActiveBinder()) {
|
34
|
+
stack_depth = binder.GetActiveBinder().stack_depth;
|
35
|
+
} else {
|
36
|
+
stack_depth = 0;
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
StackChecker<ExpressionBinder> ExpressionBinder::StackCheck(const ParsedExpression &expr, idx_t extra_stack) {
|
41
|
+
D_ASSERT(stack_depth != DConstants::INVALID_INDEX);
|
42
|
+
if (stack_depth + extra_stack >= MAXIMUM_STACK_DEPTH) {
|
43
|
+
throw BinderException("Maximum recursion depth exceeded (Maximum: %llu) while binding \"%s\"",
|
44
|
+
MAXIMUM_STACK_DEPTH, expr.ToString());
|
45
|
+
}
|
46
|
+
return StackChecker<ExpressionBinder>(*this, extra_stack);
|
47
|
+
}
|
48
|
+
|
31
49
|
BindResult ExpressionBinder::BindExpression(unique_ptr<ParsedExpression> &expr, idx_t depth, bool root_expression) {
|
50
|
+
auto stack_checker = StackCheck(*expr);
|
51
|
+
|
32
52
|
auto &expr_ref = *expr;
|
33
53
|
switch (expr_ref.expression_class) {
|
34
54
|
case ExpressionClass::BETWEEN:
|