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 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
@@ -2,7 +2,7 @@
2
2
  "name": "duckdb",
3
3
  "main": "./lib/duckdb.js",
4
4
  "types": "./lib/duckdb.d.ts",
5
- "version": "0.8.2-dev2278.0",
5
+ "version": "0.8.2-dev2320.0",
6
6
  "description": "DuckDB node.js API",
7
7
  "gypfile": true,
8
8
  "dependencies": {
@@ -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(&result, my_stream->batch_size, out, result_count, error)) {
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::TryFetchNext(QueryResult &result, unique_ptr<DataChunk> &chunk, PreservedError &error) {
166
- if (result.type == QueryResultType::STREAM_RESULT) {
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(result->types, chunk_size, QueryResult::GetArrowOptions(*result));
179
- auto &current_chunk = result->current_chunk;
180
- if (current_chunk.Valid()) {
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
- // Limit the amount we're fetching to the chunk_size
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
- appender.Append(*current_chunk.data_chunk, current_chunk.position, current_chunk.position + cur_consumption,
186
- current_chunk.data_chunk->size());
187
- current_chunk.position += cur_consumption;
188
- }
189
- while (count < chunk_size) {
190
- unique_ptr<DataChunk> data_chunk;
191
- if (!TryFetchNext(*result, data_chunk, error)) {
192
- if (result->HasError()) {
193
- error = result->GetErrorObject();
177
+ auto &current_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 (!data_chunk || data_chunk->size() == 0) {
189
+ if (scan_state.ChunkIsEmpty()) {
190
+ // The scan was successful, but an empty chunk was returned
198
191
  break;
199
192
  }
200
- if (count + data_chunk->size() > chunk_size) {
201
- // We have to split the chunk between this and the next batch
202
- idx_t available_space = chunk_size - count;
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 &current_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(QueryResult *result, idx_t chunk_size, ArrowArray *out) {
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(result, chunk_size, out, result_count, error)) {
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-dev2278"
2
+ #define DUCKDB_VERSION "0.8.2-dev2320"
3
3
  #endif
4
4
  #ifndef DUCKDB_SOURCE_ID
5
- #define DUCKDB_SOURCE_ID "a868375e85"
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(QueryResult *result, idx_t chunk_size, ArrowArray *out, idx_t &result_count,
60
- PreservedError &error);
61
- static idx_t FetchChunk(QueryResult *result, idx_t chunk_size, ArrowArray *out);
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
- struct CurrentChunk {
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, and replace params
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:
@@ -10,6 +10,8 @@
10
10
 
11
11
  #include "src/main/client_verify.cpp"
12
12
 
13
+ #include "src/main/chunk_scan_state.cpp"
14
+
13
15
  #include "src/main/config.cpp"
14
16
 
15
17
  #include "src/main/connection.cpp"
@@ -0,0 +1,2 @@
1
+ #include "src/main/chunk_scan_state/query_result.cpp"
2
+