duckdb 0.3.2-dev633.0 → 0.3.2-dev665.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/package.json +1 -1
  2. package/src/duckdb.cpp +1003 -517
  3. package/src/duckdb.hpp +5864 -5641
package/src/duckdb.cpp CHANGED
@@ -7200,7 +7200,7 @@ int ResultArrowArrayStreamWrapper::MyStreamGetSchema(struct ArrowArrayStream *st
7200
7200
  }
7201
7201
  if (result.type == QueryResultType::STREAM_RESULT) {
7202
7202
  auto &stream_result = (StreamQueryResult &)result;
7203
- if (!stream_result.is_open) {
7203
+ if (!stream_result.IsOpen()) {
7204
7204
  my_stream->last_error = "Query Stream is closed";
7205
7205
  return -1;
7206
7206
  }
@@ -7221,7 +7221,7 @@ int ResultArrowArrayStreamWrapper::MyStreamGetNext(struct ArrowArrayStream *stre
7221
7221
  }
7222
7222
  if (result.type == QueryResultType::STREAM_RESULT) {
7223
7223
  auto &stream_result = (StreamQueryResult &)result;
7224
- if (!stream_result.is_open) {
7224
+ if (!stream_result.IsOpen()) {
7225
7225
  my_stream->last_error = "Query Stream is closed";
7226
7226
  return -1;
7227
7227
  }
@@ -24080,51 +24080,43 @@ bool Printer::IsTerminal() {
24080
24080
 
24081
24081
  namespace duckdb {
24082
24082
 
24083
- void ProgressBar::ProgressBarThread() {
24084
- #ifndef DUCKDB_NO_THREADS
24085
- WaitFor(std::chrono::milliseconds(show_progress_after));
24086
- while (!stop) {
24087
- int new_percentage;
24088
- supported = executor->GetPipelinesProgress(new_percentage);
24089
- current_percentage = new_percentage;
24090
- if (supported && current_percentage > -1 && ClientConfig::GetConfig(executor->context).print_progress_bar) {
24091
- Printer::PrintProgress(current_percentage, PROGRESS_BAR_STRING.c_str(), PROGRESS_BAR_WIDTH);
24092
- }
24093
- WaitFor(std::chrono::milliseconds(time_update_bar));
24094
- }
24095
- #endif
24083
+ ProgressBar::ProgressBar(Executor &executor, idx_t show_progress_after)
24084
+ : executor(executor), show_progress_after(show_progress_after), current_percentage(-1) {
24096
24085
  }
24097
24086
 
24098
- int ProgressBar::GetCurrentPercentage() {
24087
+ double ProgressBar::GetCurrentPercentage() {
24099
24088
  return current_percentage;
24100
24089
  }
24101
24090
 
24102
24091
  void ProgressBar::Start() {
24103
- #ifndef DUCKDB_NO_THREADS
24104
- Stop(false);
24105
- stop = false;
24092
+ profiler.Start();
24106
24093
  current_percentage = 0;
24107
- progress_bar_thread = thread(&ProgressBar::ProgressBarThread, this);
24108
- #endif
24109
- }
24110
-
24111
- ProgressBar::~ProgressBar() {
24112
- Stop();
24094
+ supported = true;
24113
24095
  }
24114
24096
 
24115
- void ProgressBar::Stop(bool success) {
24116
- #ifndef DUCKDB_NO_THREADS
24117
- if (progress_bar_thread.joinable()) {
24118
- stop = true;
24119
- c.notify_one();
24120
- progress_bar_thread.join();
24121
- if (success && supported && current_percentage > 0 &&
24122
- ClientConfig::GetConfig(executor->context).print_progress_bar) {
24097
+ void ProgressBar::Update(bool final) {
24098
+ if (!supported) {
24099
+ return;
24100
+ }
24101
+ double new_percentage;
24102
+ supported = executor.GetPipelinesProgress(new_percentage);
24103
+ if (!supported) {
24104
+ return;
24105
+ }
24106
+ auto sufficient_time_elapsed = profiler.Elapsed() > show_progress_after / 1000.0;
24107
+ auto print_progress = ClientConfig::GetConfig(executor.context).print_progress_bar;
24108
+ if (new_percentage > current_percentage) {
24109
+ current_percentage = new_percentage;
24110
+ }
24111
+ if (supported && print_progress && sufficient_time_elapsed && current_percentage > -1 && print_progress) {
24112
+ if (final) {
24123
24113
  Printer::FinishProgressBarPrint(PROGRESS_BAR_STRING.c_str(), PROGRESS_BAR_WIDTH);
24114
+ } else {
24115
+ Printer::PrintProgress(current_percentage, PROGRESS_BAR_STRING.c_str(), PROGRESS_BAR_WIDTH);
24124
24116
  }
24125
24117
  }
24126
- #endif
24127
24118
  }
24119
+
24128
24120
  } // namespace duckdb
24129
24121
 
24130
24122
 
@@ -24923,8 +24915,8 @@ static void GatherNestedVector(Vector &rows, const SelectionVector &row_sel, Vec
24923
24915
  auto ptrs = FlatVector::GetData<data_ptr_t>(rows);
24924
24916
 
24925
24917
  // Build the gather locations
24926
- data_ptr_t data_locations[STANDARD_VECTOR_SIZE];
24927
- data_ptr_t mask_locations[STANDARD_VECTOR_SIZE];
24918
+ auto data_locations = unique_ptr<data_ptr_t[]>(new data_ptr_t[count]);
24919
+ auto mask_locations = unique_ptr<data_ptr_t[]>(new data_ptr_t[count]);
24928
24920
  for (idx_t i = 0; i < count; i++) {
24929
24921
  auto row_idx = row_sel.get_index(i);
24930
24922
  mask_locations[i] = ptrs[row_idx];
@@ -24932,7 +24924,7 @@ static void GatherNestedVector(Vector &rows, const SelectionVector &row_sel, Vec
24932
24924
  }
24933
24925
 
24934
24926
  // Deserialise into the selected locations
24935
- RowOperations::HeapGather(col, count, col_sel, col_no, data_locations, mask_locations);
24927
+ RowOperations::HeapGather(col, count, col_sel, col_no, data_locations.get(), mask_locations.get());
24936
24928
  }
24937
24929
 
24938
24930
  void RowOperations::Gather(Vector &rows, const SelectionVector &row_sel, Vector &col, const SelectionVector &col_sel,
@@ -30394,54 +30386,6 @@ string StringUtil::CandidatesErrorMessage(const vector<string> &strings, const s
30394
30386
 
30395
30387
 
30396
30388
 
30397
- //===----------------------------------------------------------------------===//
30398
- // DuckDB
30399
- //
30400
- // duckdb/common/profiler.hpp
30401
- //
30402
- //
30403
- //===----------------------------------------------------------------------===//
30404
-
30405
-
30406
-
30407
-
30408
-
30409
-
30410
- namespace duckdb {
30411
-
30412
- //! The profiler can be used to measure elapsed time
30413
- template <typename T>
30414
- class Profiler {
30415
- public:
30416
- //! Starts the timer
30417
- void Start() {
30418
- finished = false;
30419
- start = Tick();
30420
- }
30421
- //! Finishes timing
30422
- void End() {
30423
- end = Tick();
30424
- finished = true;
30425
- }
30426
-
30427
- //! Returns the elapsed time in seconds. If End() has been called, returns
30428
- //! the total elapsed time. Otherwise returns how far along the timer is
30429
- //! right now.
30430
- double Elapsed() const {
30431
- auto _end = finished ? end : Tick();
30432
- return std::chrono::duration_cast<std::chrono::duration<double>>(_end - start).count();
30433
- }
30434
-
30435
- private:
30436
- time_point<T> Tick() const {
30437
- return T::now();
30438
- }
30439
- time_point<T> start;
30440
- time_point<T> end;
30441
- bool finished = false;
30442
- };
30443
-
30444
- } // namespace duckdb
30445
30389
 
30446
30390
 
30447
30391
 
@@ -30454,6 +30398,7 @@ private:
30454
30398
 
30455
30399
 
30456
30400
  namespace duckdb {
30401
+ class ClientContext;
30457
30402
  class ExpressionExecutor;
30458
30403
  class PhysicalOperator;
30459
30404
  class SQLStatement;
@@ -30545,7 +30490,7 @@ private:
30545
30490
  //! Whether or not the profiler is enabled
30546
30491
  bool enabled;
30547
30492
  //! The timer used to time the execution time of the individual Physical Operators
30548
- Profiler<system_clock> op;
30493
+ Profiler op;
30549
30494
  //! The stack of Physical Operators that are currently active
30550
30495
  const PhysicalOperator *active_operator;
30551
30496
  //! A mapping of physical operators to recorded timings
@@ -30555,17 +30500,7 @@ private:
30555
30500
  //! The QueryProfiler can be used to measure timings of queries
30556
30501
  class QueryProfiler {
30557
30502
  public:
30558
- DUCKDB_API QueryProfiler()
30559
- : automatic_print_format(ProfilerPrintFormat::NONE), enabled(false), detailed_enabled(false), running(false),
30560
- query_requires_profiling(false), is_explain_analyze(false), stored_enabled(false),
30561
- stored_automatic_print_format(ProfilerPrintFormat::NONE) {
30562
- }
30563
-
30564
- //! The format to automatically print query profiling information in (default: disabled)
30565
- ProfilerPrintFormat automatic_print_format;
30566
- //! The file to save query profiling information to, instead of printing it to the console (empty = print to
30567
- //! console)
30568
- string save_location;
30503
+ DUCKDB_API QueryProfiler(ClientContext &context);
30569
30504
 
30570
30505
  public:
30571
30506
  struct TreeNode {
@@ -30589,26 +30524,12 @@ private:
30589
30524
  mutex flush_lock;
30590
30525
 
30591
30526
  public:
30592
- DUCKDB_API void Enable() {
30593
- enabled = true;
30594
- detailed_enabled = false;
30595
- }
30527
+ DUCKDB_API bool IsEnabled() const;
30528
+ DUCKDB_API bool IsDetailedEnabled() const;
30529
+ DUCKDB_API ProfilerPrintFormat GetPrintFormat() const;
30530
+ DUCKDB_API string GetSaveLocation() const;
30596
30531
 
30597
- DUCKDB_API void DetailedEnable() {
30598
- detailed_enabled = true;
30599
- }
30600
-
30601
- DUCKDB_API void Disable() {
30602
- enabled = false;
30603
- }
30604
-
30605
- DUCKDB_API bool IsEnabled() {
30606
- return enabled;
30607
- }
30608
-
30609
- bool IsDetailedEnabled() const {
30610
- return detailed_enabled;
30611
- }
30532
+ DUCKDB_API static QueryProfiler &Get(ClientContext &context);
30612
30533
 
30613
30534
  DUCKDB_API void StartQuery(string query, bool is_explain_analyze = false);
30614
30535
  DUCKDB_API void EndQuery();
@@ -30637,13 +30558,12 @@ public:
30637
30558
  void Finalize(TreeNode &node);
30638
30559
 
30639
30560
  private:
30640
- //! Whether or not query profiling is enabled
30641
- bool enabled;
30642
- //! Whether or not detailed query profiling is enabled
30643
- bool detailed_enabled;
30561
+ ClientContext &context;
30562
+
30644
30563
  //! Whether or not the query profiler is running
30645
30564
  bool running;
30646
30565
 
30566
+ //! Whether or not the query requires profiling
30647
30567
  bool query_requires_profiling;
30648
30568
 
30649
30569
  //! The root of the query tree
@@ -30651,14 +30571,11 @@ private:
30651
30571
  //! The query string
30652
30572
  string query;
30653
30573
  //! The timer used to time the execution time of the entire query
30654
- Profiler<system_clock> main_query;
30574
+ Profiler main_query;
30655
30575
  //! A map of a Physical Operator pointer to a tree node
30656
30576
  TreeMap tree_map;
30657
30577
 
30658
30578
  bool is_explain_analyze;
30659
- bool stored_enabled;
30660
- ProfilerPrintFormat stored_automatic_print_format;
30661
- string stored_save_location;
30662
30579
 
30663
30580
  public:
30664
30581
  const TreeMap &GetTreeMap() const {
@@ -30667,7 +30584,7 @@ public:
30667
30584
 
30668
30585
  private:
30669
30586
  //! The timer used to time the individual phases of the planning process
30670
- Profiler<system_clock> phase_profiler;
30587
+ Profiler phase_profiler;
30671
30588
  //! A mapping of the phase names to the timings
30672
30589
  using PhaseTimingStorage = unordered_map<string, double>;
30673
30590
  PhaseTimingStorage phase_timings;
@@ -37730,6 +37647,19 @@ T Value::GetValueInternal() const {
37730
37647
  return Cast::Operation<interval_t, T>(value_.interval);
37731
37648
  case LogicalTypeId::DECIMAL:
37732
37649
  return CastAs(LogicalType::DOUBLE).GetValueInternal<T>();
37650
+ case LogicalTypeId::ENUM: {
37651
+ switch (type_.InternalType()) {
37652
+ case PhysicalType::UINT8:
37653
+ return Cast::Operation<uint8_t, T>(value_.utinyint);
37654
+ case PhysicalType::UINT16:
37655
+ return Cast::Operation<uint16_t, T>(value_.usmallint);
37656
+ case PhysicalType::UINT32:
37657
+ return Cast::Operation<uint32_t, T>(value_.uinteger);
37658
+ default:
37659
+ throw InternalException("Invalid Internal Type for ENUMs");
37660
+ }
37661
+ }
37662
+
37733
37663
  default:
37734
37664
  throw NotImplementedException("Unimplemented type \"%s\" for GetValue()", type_.ToString());
37735
37665
  }
@@ -41627,12 +41557,15 @@ static bool TemplatedBooleanOperation(const Value &left, const Value &right) {
41627
41557
  const auto &left_type = left.type();
41628
41558
  const auto &right_type = right.type();
41629
41559
  if (left_type != right_type) {
41630
- try {
41631
- LogicalType comparison_type = BoundComparisonExpression::BindComparison(left_type, right_type);
41632
- return TemplatedBooleanOperation<OP>(left.CastAs(comparison_type), right.CastAs(comparison_type));
41633
- } catch (...) {
41560
+ Value left_copy = left;
41561
+ Value right_copy = right;
41562
+
41563
+ LogicalType comparison_type = BoundComparisonExpression::BindComparison(left_type, right_type);
41564
+ if (!left_copy.TryCastAs(comparison_type) || !right_copy.TryCastAs(comparison_type)) {
41634
41565
  return false;
41635
41566
  }
41567
+ D_ASSERT(left_copy.type() == right_copy.type());
41568
+ return TemplatedBooleanOperation<OP>(left_copy, right_copy);
41636
41569
  }
41637
41570
  switch (left_type.InternalType()) {
41638
41571
  case PhysicalType::BOOL:
@@ -52680,8 +52613,9 @@ void PhysicalSimpleAggregate::Combine(ExecutionContext &context, GlobalSinkState
52680
52613
  aggregate.function.combine(source_state, dest_state, 1);
52681
52614
  }
52682
52615
 
52616
+ auto &client_profiler = QueryProfiler::Get(context.client);
52683
52617
  context.thread.profiler.Flush(this, &source.child_executor, "child_executor", 0);
52684
- context.client.profiler->Flush(context.thread.profiler);
52618
+ client_profiler.Flush(context.thread.profiler);
52685
52619
  }
52686
52620
 
52687
52621
  SinkFinalizeType PhysicalSimpleAggregate::Finalize(Pipeline &pipeline, Event &event, ClientContext &context,
@@ -54486,7 +54420,8 @@ SinkResultType PhysicalExplainAnalyze::Sink(ExecutionContext &context, GlobalSin
54486
54420
  SinkFinalizeType PhysicalExplainAnalyze::Finalize(Pipeline &pipeline, Event &event, ClientContext &context,
54487
54421
  GlobalSinkState &gstate_p) const {
54488
54422
  auto &gstate = (ExplainAnalyzeStateGlobalState &)gstate_p;
54489
- gstate.analyzed_plan = context.profiler->ToString();
54423
+ auto &profiler = QueryProfiler::Get(context);
54424
+ gstate.analyzed_plan = profiler.ToString();
54490
54425
  return SinkFinalizeType::READY;
54491
54426
  }
54492
54427
 
@@ -57267,8 +57202,9 @@ SinkResultType PhysicalHashJoin::Sink(ExecutionContext &context, GlobalSinkState
57267
57202
 
57268
57203
  void PhysicalHashJoin::Combine(ExecutionContext &context, GlobalSinkState &gstate, LocalSinkState &lstate) const {
57269
57204
  auto &state = (HashJoinLocalState &)lstate;
57205
+ auto &client_profiler = QueryProfiler::Get(context.client);
57270
57206
  context.thread.profiler.Flush(this, &state.build_executor, "build_executor", 1);
57271
- context.client.profiler->Flush(context.thread.profiler);
57207
+ client_profiler.Flush(context.thread.profiler);
57272
57208
  }
57273
57209
 
57274
57210
  //===--------------------------------------------------------------------===//
@@ -58032,8 +57968,10 @@ SinkResultType PhysicalNestedLoopJoin::Sink(ExecutionContext &context, GlobalSin
58032
57968
 
58033
57969
  void PhysicalNestedLoopJoin::Combine(ExecutionContext &context, GlobalSinkState &gstate, LocalSinkState &lstate) const {
58034
57970
  auto &state = (NestedLoopJoinLocalState &)lstate;
57971
+ auto &client_profiler = QueryProfiler::Get(context.client);
57972
+
58035
57973
  context.thread.profiler.Flush(this, &state.rhs_executor, "rhs_executor", 1);
58036
- context.client.profiler->Flush(context.thread.profiler);
57974
+ client_profiler.Flush(context.thread.profiler);
58037
57975
  }
58038
57976
 
58039
57977
  SinkFinalizeType PhysicalNestedLoopJoin::Finalize(Pipeline &pipeline, Event &event, ClientContext &context,
@@ -58465,8 +58403,10 @@ SinkResultType PhysicalPiecewiseMergeJoin::Sink(ExecutionContext &context, Globa
58465
58403
  void PhysicalPiecewiseMergeJoin::Combine(ExecutionContext &context, GlobalSinkState &gstate,
58466
58404
  LocalSinkState &lstate) const {
58467
58405
  auto &state = (MergeJoinLocalState &)lstate;
58406
+ auto &client_profiler = QueryProfiler::Get(context.client);
58407
+
58468
58408
  context.thread.profiler.Flush(this, &state.rhs_executor, "rhs_executor", 1);
58469
- context.client.profiler->Flush(context.thread.profiler);
58409
+ client_profiler.Flush(context.thread.profiler);
58470
58410
  }
58471
58411
 
58472
58412
  //===--------------------------------------------------------------------===//
@@ -59051,12 +58991,13 @@ public:
59051
58991
  : ExecutorTask(context), event(move(event_p)), context(context), state(state) {
59052
58992
  }
59053
58993
 
59054
- void ExecuteTask() override {
58994
+ TaskExecutionResult ExecuteTask(TaskExecutionMode mode) override {
59055
58995
  // Initialize merge sorted and iterate until done
59056
58996
  auto &global_sort_state = state.global_sort_state;
59057
58997
  MergeSorter merge_sorter(global_sort_state, BufferManager::GetBufferManager(context));
59058
58998
  merge_sorter.PerformInMergeRound();
59059
58999
  event->FinishTask();
59000
+ return TaskExecutionResult::TASK_FINISHED;
59060
59001
  }
59061
59002
 
59062
59003
  private:
@@ -62392,8 +62333,9 @@ unique_ptr<LocalSinkState> PhysicalInsert::GetLocalSinkState(ExecutionContext &c
62392
62333
 
62393
62334
  void PhysicalInsert::Combine(ExecutionContext &context, GlobalSinkState &gstate, LocalSinkState &lstate) const {
62394
62335
  auto &state = (InsertLocalState &)lstate;
62336
+ auto &client_profiler = QueryProfiler::Get(context.client);
62395
62337
  context.thread.profiler.Flush(this, &state.default_executor, "default_executor", 1);
62396
- context.client.profiler->Flush(context.thread.profiler);
62338
+ client_profiler.Flush(context.thread.profiler);
62397
62339
  }
62398
62340
 
62399
62341
  //===--------------------------------------------------------------------===//
@@ -62599,8 +62541,9 @@ unique_ptr<LocalSinkState> PhysicalUpdate::GetLocalSinkState(ExecutionContext &c
62599
62541
 
62600
62542
  void PhysicalUpdate::Combine(ExecutionContext &context, GlobalSinkState &gstate, LocalSinkState &lstate) const {
62601
62543
  auto &state = (UpdateLocalState &)lstate;
62544
+ auto &client_profiler = QueryProfiler::Get(context.client);
62602
62545
  context.thread.profiler.Flush(this, &state.default_executor, "default_executor", 1);
62603
- context.client.profiler->Flush(context.thread.profiler);
62546
+ client_profiler.Flush(context.thread.profiler);
62604
62547
  }
62605
62548
 
62606
62549
  //===--------------------------------------------------------------------===//
@@ -65567,6 +65510,7 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalChunkGet &
65567
65510
 
65568
65511
 
65569
65512
 
65513
+
65570
65514
  namespace duckdb {
65571
65515
 
65572
65516
  static bool CanPlanIndexJoin(Transaction &transaction, TableScanBindData *bind_data, PhysicalTableScan &scan) {
@@ -65586,6 +65530,30 @@ static bool CanPlanIndexJoin(Transaction &transaction, TableScanBindData *bind_d
65586
65530
  return true;
65587
65531
  }
65588
65532
 
65533
+ bool ExtractNumericValue(Value val, int64_t &result) {
65534
+ if (!val.type().IsIntegral()) {
65535
+ switch (val.type().InternalType()) {
65536
+ case PhysicalType::INT16:
65537
+ result = val.GetValueUnsafe<int16_t>();
65538
+ break;
65539
+ case PhysicalType::INT32:
65540
+ result = val.GetValueUnsafe<int32_t>();
65541
+ break;
65542
+ case PhysicalType::INT64:
65543
+ result = val.GetValueUnsafe<int64_t>();
65544
+ break;
65545
+ default:
65546
+ return false;
65547
+ }
65548
+ } else {
65549
+ if (!val.TryCastAs(LogicalType::BIGINT)) {
65550
+ return false;
65551
+ }
65552
+ result = val.GetValue<int64_t>();
65553
+ }
65554
+ return true;
65555
+ }
65556
+
65589
65557
  void CheckForPerfectJoinOpt(LogicalComparisonJoin &op, PerfectHashJoinStats &join_state) {
65590
65558
  // we only do this optimization for inner joins
65591
65559
  if (op.join_type != JoinType::INNER) {
@@ -65618,7 +65586,14 @@ void CheckForPerfectJoinOpt(LogicalComparisonJoin &op, PerfectHashJoinStats &joi
65618
65586
  if (stats_build->min.is_null || stats_build->max.is_null) {
65619
65587
  return;
65620
65588
  }
65621
- auto build_range = stats_build->max - stats_build->min; // Join Keys Range
65589
+ int64_t min_value, max_value;
65590
+ if (!ExtractNumericValue(stats_build->min, min_value) || !ExtractNumericValue(stats_build->max, max_value)) {
65591
+ return;
65592
+ }
65593
+ int64_t build_range;
65594
+ if (!TrySubtractOperator::Operation(max_value, min_value, build_range)) {
65595
+ return;
65596
+ }
65622
65597
 
65623
65598
  // Fill join_stats for invisible join
65624
65599
  auto stats_probe = reinterpret_cast<NumericStatistics *>(op.join_stats[1].get()); // rhs stats
@@ -65630,26 +65605,7 @@ void CheckForPerfectJoinOpt(LogicalComparisonJoin &op, PerfectHashJoinStats &joi
65630
65605
  join_state.build_min = stats_build->min;
65631
65606
  join_state.build_max = stats_build->max;
65632
65607
  join_state.estimated_cardinality = op.estimated_cardinality;
65633
- if (!build_range.type().IsIntegral()) {
65634
- switch (build_range.type().InternalType()) {
65635
- case PhysicalType::INT16:
65636
- join_state.build_range = build_range.value_.smallint;
65637
- break;
65638
- case PhysicalType::INT32:
65639
- join_state.build_range = build_range.value_.integer;
65640
- break;
65641
- case PhysicalType::INT64:
65642
- join_state.build_range = build_range.value_.bigint;
65643
- break;
65644
- case PhysicalType::INT128:
65645
- // we do not support hugeint for this optimization
65646
- return;
65647
- default:
65648
- throw InternalException("Invalid Physical Type for Decimals");
65649
- }
65650
- } else {
65651
- join_state.build_range = build_range.GetValue<idx_t>(); // cast integer types into idx_t
65652
- }
65608
+ join_state.build_range = build_range;
65653
65609
  if (join_state.build_range > MAX_BUILD_SIZE || stats_probe->max.is_null || stats_probe->min.is_null) {
65654
65610
  return;
65655
65611
  }
@@ -68596,25 +68552,27 @@ private:
68596
68552
  };
68597
68553
 
68598
68554
  unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(unique_ptr<LogicalOperator> op) {
68555
+ auto &profiler = QueryProfiler::Get(context);
68556
+
68599
68557
  // first resolve column references
68600
- context.profiler->StartPhase("column_binding");
68558
+ profiler.StartPhase("column_binding");
68601
68559
  ColumnBindingResolver resolver;
68602
68560
  resolver.VisitOperator(*op);
68603
- context.profiler->EndPhase();
68561
+ profiler.EndPhase();
68604
68562
 
68605
68563
  // now resolve types of all the operators
68606
- context.profiler->StartPhase("resolve_types");
68564
+ profiler.StartPhase("resolve_types");
68607
68565
  op->ResolveOperatorTypes();
68608
- context.profiler->EndPhase();
68566
+ profiler.EndPhase();
68609
68567
 
68610
68568
  // extract dependencies from the logical plan
68611
68569
  DependencyExtractor extractor(dependencies);
68612
68570
  extractor.VisitOperator(*op);
68613
68571
 
68614
68572
  // then create the main physical plan
68615
- context.profiler->StartPhase("create_plan");
68573
+ profiler.StartPhase("create_plan");
68616
68574
  auto plan = CreatePlan(*op);
68617
- context.profiler->EndPhase();
68575
+ profiler.EndPhase();
68618
68576
  return plan;
68619
68577
  }
68620
68578
 
@@ -68976,6 +68934,7 @@ public:
68976
68934
  idx_t radix_p)
68977
68935
  : ExecutorTask(executor), event(move(event_p)), state(state_p), radix(radix_p) {
68978
68936
  }
68937
+
68979
68938
  static void FinalizeHT(RadixHTGlobalState &gstate, idx_t radix) {
68980
68939
  D_ASSERT(gstate.partition_info.n_partitions <= gstate.finalized_hts.size());
68981
68940
  D_ASSERT(gstate.finalized_hts[radix]);
@@ -68988,9 +68947,10 @@ public:
68988
68947
  gstate.finalized_hts[radix]->Finalize();
68989
68948
  }
68990
68949
 
68991
- void ExecuteTask() override {
68950
+ TaskExecutionResult ExecuteTask(TaskExecutionMode mode) override {
68992
68951
  FinalizeHT(state, radix);
68993
68952
  event->FinishTask();
68953
+ return TaskExecutionResult::TASK_FINISHED;
68994
68954
  }
68995
68955
 
68996
68956
  private:
@@ -77592,6 +77552,7 @@ void BuiltinFunctions::Initialize() {
77592
77552
  RegisterRegressiveAggregates();
77593
77553
 
77594
77554
  RegisterDateFunctions();
77555
+ RegisterEnumFunctions();
77595
77556
  RegisterGenericFunctions();
77596
77557
  RegisterMathFunctions();
77597
77558
  RegisterOperators();
@@ -78092,8 +78053,9 @@ struct PragmaFunctions {
78092
78053
  namespace duckdb {
78093
78054
 
78094
78055
  static void PragmaEnableProfilingStatement(ClientContext &context, const FunctionParameters &parameters) {
78095
- context.profiler->automatic_print_format = ProfilerPrintFormat::QUERY_TREE;
78096
- context.profiler->Enable();
78056
+ auto &config = ClientConfig::GetConfig(context);
78057
+ config.profiler_print_format = ProfilerPrintFormat::QUERY_TREE;
78058
+ config.enable_profiler = true;
78097
78059
  }
78098
78060
 
78099
78061
  void RegisterEnableProfiling(BuiltinFunctions &set) {
@@ -78105,8 +78067,9 @@ void RegisterEnableProfiling(BuiltinFunctions &set) {
78105
78067
  }
78106
78068
 
78107
78069
  static void PragmaDisableProfiling(ClientContext &context, const FunctionParameters &parameters) {
78108
- context.profiler->Disable();
78109
- context.profiler->automatic_print_format = ProfilerPrintFormat::NONE;
78070
+ auto &config = ClientConfig::GetConfig(context);
78071
+ config.enable_profiler = false;
78072
+ config.profiler_print_format = ProfilerPrintFormat::NONE;
78110
78073
  }
78111
78074
 
78112
78075
  static void PragmaEnableProgressBar(ClientContext &context, const FunctionParameters &parameters) {
@@ -82094,6 +82057,163 @@ void BuiltinFunctions::RegisterDateFunctions() {
82094
82057
  Register<ToIntervalFun>();
82095
82058
  }
82096
82059
 
82060
+ } // namespace duckdb
82061
+ //===----------------------------------------------------------------------===//
82062
+ // DuckDB
82063
+ //
82064
+ // duckdb/function/scalar/enum_functions.hpp
82065
+ //
82066
+ //
82067
+ //===----------------------------------------------------------------------===//
82068
+
82069
+
82070
+
82071
+
82072
+
82073
+
82074
+ namespace duckdb {
82075
+
82076
+ struct EnumFirst {
82077
+ static void RegisterFunction(BuiltinFunctions &set);
82078
+ };
82079
+
82080
+ struct EnumLast {
82081
+ static void RegisterFunction(BuiltinFunctions &set);
82082
+ };
82083
+
82084
+ struct EnumRange {
82085
+ static void RegisterFunction(BuiltinFunctions &set);
82086
+ };
82087
+
82088
+ struct EnumRangeBoundary {
82089
+ static void RegisterFunction(BuiltinFunctions &set);
82090
+ };
82091
+
82092
+ } // namespace duckdb
82093
+
82094
+
82095
+ namespace duckdb {
82096
+
82097
+ static void EnumFirstFunction(DataChunk &input, ExpressionState &state, Vector &result) {
82098
+ D_ASSERT(input.GetTypes().size() == 1);
82099
+ auto &enum_vector = EnumType::GetValuesInsertOrder(input.GetTypes()[0]);
82100
+ auto val = Value(enum_vector.GetValue(0));
82101
+ result.Reference(val);
82102
+ }
82103
+
82104
+ static void EnumLastFunction(DataChunk &input, ExpressionState &state, Vector &result) {
82105
+ D_ASSERT(input.GetTypes().size() == 1);
82106
+ auto enum_size = EnumType::GetSize(input.GetTypes()[0]);
82107
+ auto &enum_vector = EnumType::GetValuesInsertOrder(input.GetTypes()[0]);
82108
+ auto val = Value(enum_vector.GetValue(enum_size - 1));
82109
+ result.Reference(val);
82110
+ }
82111
+
82112
+ static void EnumRangeFunction(DataChunk &input, ExpressionState &state, Vector &result) {
82113
+ D_ASSERT(input.GetTypes().size() == 1);
82114
+ auto enum_size = EnumType::GetSize(input.GetTypes()[0]);
82115
+ auto &enum_vector = EnumType::GetValuesInsertOrder(input.GetTypes()[0]);
82116
+ vector<Value> enum_values;
82117
+ for (idx_t i = 0; i < enum_size; i++) {
82118
+ enum_values.emplace_back(enum_vector.GetValue(i));
82119
+ }
82120
+ auto val = Value::LIST(enum_values);
82121
+ result.Reference(val);
82122
+ }
82123
+
82124
+ static void EnumRangeBoundaryFunction(DataChunk &input, ExpressionState &state, Vector &result) {
82125
+ D_ASSERT(input.GetTypes().size() == 2);
82126
+ idx_t start, end;
82127
+ auto first_param = input.GetValue(0, 0);
82128
+ auto second_param = input.GetValue(1, 0);
82129
+
82130
+ auto &enum_vector = first_param.is_null ? EnumType::GetValuesInsertOrder(input.GetTypes()[1])
82131
+ : EnumType::GetValuesInsertOrder(input.GetTypes()[0]);
82132
+
82133
+ if (first_param.is_null) {
82134
+ start = 0;
82135
+ } else {
82136
+ start = first_param.GetValue<uint32_t>();
82137
+ }
82138
+ if (second_param.is_null) {
82139
+ end = EnumType::GetSize(input.GetTypes()[0]);
82140
+ } else {
82141
+ end = second_param.GetValue<uint32_t>() + 1;
82142
+ }
82143
+ vector<Value> enum_values;
82144
+ for (idx_t i = start; i < end; i++) {
82145
+ enum_values.emplace_back(enum_vector.GetValue(i));
82146
+ }
82147
+ Value val;
82148
+ if (enum_values.empty()) {
82149
+ val = Value::EMPTYLIST(LogicalType::VARCHAR);
82150
+ } else {
82151
+ val = Value::LIST(enum_values);
82152
+ }
82153
+ result.Reference(val);
82154
+ }
82155
+
82156
+ unique_ptr<FunctionData> BindEnumFunction(ClientContext &context, ScalarFunction &bound_function,
82157
+ vector<unique_ptr<Expression>> &arguments) {
82158
+ if (arguments[0]->return_type.id() != LogicalTypeId::ENUM) {
82159
+ throw BinderException("This function needs an ENUM as an argument");
82160
+ }
82161
+ return nullptr;
82162
+ }
82163
+
82164
+ unique_ptr<FunctionData> BindEnumRangeBoundaryFunction(ClientContext &context, ScalarFunction &bound_function,
82165
+ vector<unique_ptr<Expression>> &arguments) {
82166
+ if (arguments[0]->return_type.id() != LogicalTypeId::ENUM && arguments[0]->return_type != LogicalType::SQLNULL) {
82167
+ throw BinderException("This function needs an ENUM as an argument");
82168
+ }
82169
+ if (arguments[1]->return_type.id() != LogicalTypeId::ENUM && arguments[1]->return_type != LogicalType::SQLNULL) {
82170
+ throw BinderException("This function needs an ENUM as an argument");
82171
+ }
82172
+ if (arguments[0]->return_type == LogicalType::SQLNULL && arguments[1]->return_type == LogicalType::SQLNULL) {
82173
+ throw BinderException("This function needs an ENUM as an argument");
82174
+ }
82175
+ if (arguments[0]->return_type.id() == LogicalTypeId::ENUM &&
82176
+ arguments[1]->return_type.id() == LogicalTypeId::ENUM &&
82177
+ arguments[0]->return_type != arguments[1]->return_type) {
82178
+
82179
+ throw BinderException("The parameters need to link to ONLY one enum OR be NULL ");
82180
+ }
82181
+ return nullptr;
82182
+ }
82183
+
82184
+ void EnumFirst::RegisterFunction(BuiltinFunctions &set) {
82185
+ set.AddFunction(ScalarFunction("enum_first", {LogicalType::ANY}, LogicalType::VARCHAR, EnumFirstFunction, false,
82186
+ BindEnumFunction));
82187
+ }
82188
+
82189
+ void EnumLast::RegisterFunction(BuiltinFunctions &set) {
82190
+ set.AddFunction(ScalarFunction("enum_last", {LogicalType::ANY}, LogicalType::VARCHAR, EnumLastFunction, false,
82191
+ BindEnumFunction));
82192
+ }
82193
+
82194
+ void EnumRange::RegisterFunction(BuiltinFunctions &set) {
82195
+ set.AddFunction(ScalarFunction("enum_range", {LogicalType::ANY}, LogicalType::LIST(LogicalType::VARCHAR),
82196
+ EnumRangeFunction, false, BindEnumFunction));
82197
+ }
82198
+
82199
+ void EnumRangeBoundary::RegisterFunction(BuiltinFunctions &set) {
82200
+ set.AddFunction(ScalarFunction("enum_range_boundary", {LogicalType::ANY, LogicalType::ANY},
82201
+ LogicalType::LIST(LogicalType::VARCHAR), EnumRangeBoundaryFunction, false,
82202
+ BindEnumRangeBoundaryFunction));
82203
+ }
82204
+
82205
+ } // namespace duckdb
82206
+
82207
+
82208
+ namespace duckdb {
82209
+
82210
+ void BuiltinFunctions::RegisterEnumFunctions() {
82211
+ Register<EnumFirst>();
82212
+ Register<EnumLast>();
82213
+ Register<EnumRange>();
82214
+ Register<EnumRangeBoundary>();
82215
+ }
82216
+
82097
82217
  } // namespace duckdb
82098
82218
  //===----------------------------------------------------------------------===//
82099
82219
  // DuckDB
@@ -91738,8 +91858,7 @@ unique_ptr<FunctionData> BindSystemFunction(ClientContext &context, ScalarFuncti
91738
91858
 
91739
91859
  static void CurrentQueryFunction(DataChunk &input, ExpressionState &state, Vector &result) {
91740
91860
  auto &info = SystemBindData::GetFrom(state);
91741
-
91742
- Value val(info.context.query);
91861
+ Value val(info.context.GetCurrentQuery());
91743
91862
  result.Reference(val);
91744
91863
  }
91745
91864
 
@@ -91981,6 +92100,21 @@ void ScalarFunction::NopFunction(DataChunk &input, ExpressionState &state, Vecto
91981
92100
 
91982
92101
 
91983
92102
 
92103
+ //===----------------------------------------------------------------------===//
92104
+ // DuckDB
92105
+ //
92106
+ // duckdb/common/thread.hpp
92107
+ //
92108
+ //
92109
+ //===----------------------------------------------------------------------===//
92110
+
92111
+
92112
+
92113
+ #include <thread>
92114
+
92115
+ namespace duckdb {
92116
+ using std::thread;
92117
+ }
91984
92118
 
91985
92119
  #include <map>
91986
92120
  #include <condition_variable>
@@ -92126,7 +92260,7 @@ private:
92126
92260
  //! Gets Arrow Table's Cardinality
92127
92261
  static unique_ptr<NodeStatistics> ArrowScanCardinality(ClientContext &context, const FunctionData *bind_data);
92128
92262
  //! Gets the progress on the table scan, used for Progress Bars
92129
- static int ArrowProgress(ClientContext &context, const FunctionData *bind_data_p);
92263
+ static double ArrowProgress(ClientContext &context, const FunctionData *bind_data_p);
92130
92264
  };
92131
92265
 
92132
92266
  } // namespace duckdb
@@ -93225,12 +93359,12 @@ unique_ptr<NodeStatistics> ArrowTableFunction::ArrowScanCardinality(ClientContex
93225
93359
  return make_unique<NodeStatistics>(bind_data.number_of_rows, bind_data.number_of_rows);
93226
93360
  }
93227
93361
 
93228
- int ArrowTableFunction::ArrowProgress(ClientContext &context, const FunctionData *bind_data_p) {
93362
+ double ArrowTableFunction::ArrowProgress(ClientContext &context, const FunctionData *bind_data_p) {
93229
93363
  auto &bind_data = (const ArrowScanFunctionData &)*bind_data_p;
93230
93364
  if (bind_data.number_of_rows == 0) {
93231
93365
  return 100;
93232
93366
  }
93233
- auto percentage = bind_data.lines_read * 100 / bind_data.number_of_rows;
93367
+ auto percentage = bind_data.lines_read * 100.0 / bind_data.number_of_rows;
93234
93368
  return percentage;
93235
93369
  }
93236
93370
 
@@ -94915,12 +95049,12 @@ static void ReadCSVAddNamedParameters(TableFunction &table_function) {
94915
95049
  table_function.named_parameters["skip"] = LogicalType::BIGINT;
94916
95050
  }
94917
95051
 
94918
- int CSVReaderProgress(ClientContext &context, const FunctionData *bind_data_p) {
95052
+ double CSVReaderProgress(ClientContext &context, const FunctionData *bind_data_p) {
94919
95053
  auto &bind_data = (ReadCSVData &)*bind_data_p;
94920
95054
  if (bind_data.file_size == 0) {
94921
95055
  return 100;
94922
95056
  }
94923
- auto percentage = bind_data.bytes_read * 100 / bind_data.file_size;
95057
+ auto percentage = (bind_data.bytes_read * 100.0) / bind_data.file_size;
94924
95058
  return percentage;
94925
95059
  }
94926
95060
 
@@ -98134,14 +98268,14 @@ bool TableScanParallelStateNext(ClientContext &context, const FunctionData *bind
98134
98268
  state.column_ids);
98135
98269
  }
98136
98270
 
98137
- int TableScanProgress(ClientContext &context, const FunctionData *bind_data_p) {
98271
+ double TableScanProgress(ClientContext &context, const FunctionData *bind_data_p) {
98138
98272
  auto &bind_data = (TableScanBindData &)*bind_data_p;
98139
98273
  idx_t total_rows = bind_data.table->storage->GetTotalRows();
98140
98274
  if (total_rows == 0 || total_rows < STANDARD_VECTOR_SIZE) {
98141
98275
  //! Table is either empty or smaller than a vector size, so it is finished
98142
98276
  return 100;
98143
98277
  }
98144
- auto percentage = (bind_data.chunk_count * STANDARD_VECTOR_SIZE * 100) / total_rows;
98278
+ auto percentage = double(bind_data.chunk_count * STANDARD_VECTOR_SIZE * 100.0) / total_rows;
98145
98279
  if (percentage > 100) {
98146
98280
  //! In case the last chunk has less elements than STANDARD_VECTOR_SIZE, if our percentage is over 100
98147
98281
  //! It means we finished this table.
@@ -100877,28 +101011,27 @@ private:
100877
101011
 
100878
101012
  namespace duckdb {
100879
101013
 
100880
- class ClientContextLock {
100881
- public:
100882
- explicit ClientContextLock(mutex &context_lock) : client_guard(context_lock) {
100883
- }
100884
-
100885
- ~ClientContextLock() {
100886
- }
100887
-
100888
- private:
100889
- lock_guard<mutex> client_guard;
101014
+ struct ActiveQueryContext {
101015
+ //! The query that is currently being executed
101016
+ string query;
101017
+ //! The currently open result
101018
+ BaseQueryResult *open_result = nullptr;
101019
+ //! Prepared statement data
101020
+ shared_ptr<PreparedStatementData> prepared;
101021
+ //! The query executor
101022
+ unique_ptr<Executor> executor;
101023
+ //! The progress bar
101024
+ unique_ptr<ProgressBar> progress_bar;
100890
101025
  };
100891
101026
 
100892
101027
  ClientContext::ClientContext(shared_ptr<DatabaseInstance> database)
100893
- : profiler(make_unique<QueryProfiler>()), query_profiler_history(make_unique<QueryProfilerHistory>()),
100894
- db(move(database)), transaction(db->GetTransactionManager(), *this), interrupted(false), executor(*this),
101028
+ : profiler(make_unique<QueryProfiler>(*this)), query_profiler_history(make_unique<QueryProfilerHistory>()),
101029
+ db(move(database)), transaction(db->GetTransactionManager(), *this), interrupted(false),
100895
101030
  temporary_objects(make_unique<SchemaCatalogEntry>(&db->GetCatalog(), TEMP_SCHEMA, true)),
100896
101031
  catalog_search_path(make_unique<CatalogSearchPath>(*this)),
100897
- file_opener(make_unique<ClientContextFileOpener>(*this)), open_result(nullptr) {
101032
+ file_opener(make_unique<ClientContextFileOpener>(*this)) {
100898
101033
  std::random_device rd;
100899
101034
  random_engine.seed(rd());
100900
-
100901
- progress_bar = make_unique<ProgressBar>(&executor, config.wait_time);
100902
101035
  }
100903
101036
 
100904
101037
  ClientContext::~ClientContext() {
@@ -100925,87 +101058,162 @@ void ClientContext::Destroy() {
100925
101058
  CleanupInternal(*lock);
100926
101059
  }
100927
101060
 
100928
- void ClientContext::Cleanup() {
100929
- auto lock = LockContext();
100930
- CleanupInternal(*lock);
101061
+ unique_ptr<DataChunk> ClientContext::Fetch(ClientContextLock &lock, StreamQueryResult &result) {
101062
+ D_ASSERT(IsActiveResult(lock, &result));
101063
+ D_ASSERT(active_query->executor);
101064
+ return FetchInternal(lock, *active_query->executor, result);
100931
101065
  }
100932
101066
 
100933
- unique_ptr<DataChunk> ClientContext::Fetch() {
100934
- auto lock = LockContext();
100935
- if (!open_result) {
100936
- throw InternalException("Fetch was called, but there is no open result (or the result was previously closed)");
100937
- }
101067
+ unique_ptr<DataChunk> ClientContext::FetchInternal(ClientContextLock &lock, Executor &executor,
101068
+ BaseQueryResult &result) {
101069
+ bool invalidate_query = true;
100938
101070
  try {
100939
101071
  // fetch the chunk and return it
100940
- auto chunk = FetchInternal(*lock);
101072
+ auto chunk = executor.FetchChunk();
101073
+ if (!chunk || chunk->size() == 0) {
101074
+ CleanupInternal(lock, &result);
101075
+ }
100941
101076
  return chunk;
101077
+ } catch (StandardException &ex) {
101078
+ // standard exceptions do not invalidate the current transaction
101079
+ result.error = ex.what();
101080
+ invalidate_query = false;
100942
101081
  } catch (std::exception &ex) {
100943
- open_result->error = ex.what();
101082
+ result.error = ex.what();
100944
101083
  } catch (...) { // LCOV_EXCL_START
100945
- open_result->error = "Unhandled exception in Fetch";
101084
+ result.error = "Unhandled exception in FetchInternal";
100946
101085
  } // LCOV_EXCL_STOP
100947
- open_result->success = false;
100948
- CleanupInternal(*lock);
101086
+ result.success = false;
101087
+ CleanupInternal(lock, &result, invalidate_query);
100949
101088
  return nullptr;
100950
101089
  }
100951
101090
 
100952
- string ClientContext::FinalizeQuery(ClientContextLock &lock, bool success) {
101091
+ void ClientContext::BeginTransactionInternal(ClientContextLock &lock, bool requires_valid_transaction) {
101092
+ // check if we are on AutoCommit. In this case we should start a transaction
101093
+ D_ASSERT(!active_query);
101094
+ if (requires_valid_transaction && transaction.HasActiveTransaction() &&
101095
+ transaction.ActiveTransaction().IsInvalidated()) {
101096
+ throw Exception("Failed: transaction has been invalidated!");
101097
+ }
101098
+ active_query = make_unique<ActiveQueryContext>();
101099
+ if (transaction.IsAutoCommit()) {
101100
+ transaction.BeginTransaction();
101101
+ }
101102
+ }
101103
+
101104
+ void ClientContext::BeginQueryInternal(ClientContextLock &lock, const string &query) {
101105
+ BeginTransactionInternal(lock, false);
101106
+ LogQueryInternal(lock, query);
101107
+ active_query->query = query;
101108
+ query_progress = -1;
101109
+ ActiveTransaction().active_query = db->GetTransactionManager().GetQueryNumber();
101110
+ }
101111
+
101112
+ string ClientContext::EndQueryInternal(ClientContextLock &lock, bool success, bool invalidate_transaction) {
100953
101113
  profiler->EndQuery();
100954
- executor.Reset();
100955
101114
 
101115
+ D_ASSERT(active_query.get());
100956
101116
  string error;
100957
- if (transaction.HasActiveTransaction()) {
100958
- ActiveTransaction().active_query = MAXIMUM_QUERY_ID;
100959
- // Move the query profiler into the history
100960
- auto &prev_profilers = query_profiler_history->GetPrevProfilers();
100961
- prev_profilers.emplace_back(transaction.ActiveTransaction().active_query, move(profiler));
100962
- // Reinitialize the query profiler
100963
- profiler = make_unique<QueryProfiler>();
100964
- // Propagate settings of the saved query into the new profiler.
100965
- profiler->Propagate(*prev_profilers.back().second);
100966
- if (prev_profilers.size() >= query_profiler_history->GetPrevProfilersSize()) {
100967
- prev_profilers.pop_front();
100968
- }
100969
- try {
101117
+ try {
101118
+ if (transaction.HasActiveTransaction()) {
101119
+ // Move the query profiler into the history
101120
+ auto &prev_profilers = query_profiler_history->GetPrevProfilers();
101121
+ prev_profilers.emplace_back(transaction.ActiveTransaction().active_query, move(profiler));
101122
+ // Reinitialize the query profiler
101123
+ profiler = make_unique<QueryProfiler>(*this);
101124
+ // Propagate settings of the saved query into the new profiler.
101125
+ profiler->Propagate(*prev_profilers.back().second);
101126
+ if (prev_profilers.size() >= query_profiler_history->GetPrevProfilersSize()) {
101127
+ prev_profilers.pop_front();
101128
+ }
101129
+
101130
+ ActiveTransaction().active_query = MAXIMUM_QUERY_ID;
100970
101131
  if (transaction.IsAutoCommit()) {
100971
101132
  if (success) {
100972
- // query was successful: commit
100973
101133
  transaction.Commit();
100974
101134
  } else {
100975
- // query was unsuccessful: rollback
100976
101135
  transaction.Rollback();
100977
101136
  }
101137
+ } else if (invalidate_transaction) {
101138
+ D_ASSERT(!success);
101139
+ ActiveTransaction().Invalidate();
100978
101140
  }
100979
- } catch (std::exception &ex) {
100980
- error = ex.what();
100981
- } catch (...) { // LCOV_EXCL_START
100982
- error = "Unhandled exception!";
100983
- } // LCOV_EXCL_STOP
100984
- }
101141
+ }
101142
+ } catch (std::exception &ex) {
101143
+ error = ex.what();
101144
+ } catch (...) { // LCOV_EXCL_START
101145
+ error = "Unhandled exception!";
101146
+ } // LCOV_EXCL_STOP
101147
+ active_query.reset();
101148
+ query_progress = -1;
100985
101149
  return error;
100986
101150
  }
100987
101151
 
100988
- void ClientContext::CleanupInternal(ClientContextLock &lock) {
100989
- if (!open_result) {
100990
- // no result currently open
101152
+ void ClientContext::CleanupInternal(ClientContextLock &lock, BaseQueryResult *result, bool invalidate_transaction) {
101153
+ if (!active_query) {
101154
+ // no query currently active
100991
101155
  return;
100992
101156
  }
101157
+ if (active_query->executor) {
101158
+ active_query->executor->CancelTasks();
101159
+ }
101160
+ active_query->progress_bar.reset();
100993
101161
 
100994
- auto error = FinalizeQuery(lock, open_result->success);
100995
- if (open_result->success) {
101162
+ auto error = EndQueryInternal(lock, result ? result->success : false, invalidate_transaction);
101163
+ if (result && result->success) {
100996
101164
  // if an error occurred while committing report it in the result
100997
- open_result->error = error;
100998
- open_result->success = error.empty();
101165
+ result->error = error;
101166
+ result->success = error.empty();
100999
101167
  }
101168
+ D_ASSERT(!active_query);
101169
+ }
101000
101170
 
101001
- open_result->is_open = false;
101002
- open_result = nullptr;
101171
+ Executor &ClientContext::GetExecutor() {
101172
+ D_ASSERT(active_query);
101173
+ D_ASSERT(active_query->executor);
101174
+ return *active_query->executor;
101175
+ }
101003
101176
 
101004
- this->query = string();
101177
+ const string &ClientContext::GetCurrentQuery() {
101178
+ D_ASSERT(active_query);
101179
+ return active_query->query;
101005
101180
  }
101006
101181
 
101007
- unique_ptr<DataChunk> ClientContext::FetchInternal(ClientContextLock &) {
101008
- return executor.FetchChunk();
101182
+ unique_ptr<QueryResult> ClientContext::FetchResultInternal(ClientContextLock &lock, PendingQueryResult &pending,
101183
+ bool allow_stream_result) {
101184
+ D_ASSERT(active_query);
101185
+ D_ASSERT(active_query->open_result == &pending);
101186
+ D_ASSERT(active_query->prepared);
101187
+ auto &prepared = *active_query->prepared;
101188
+ bool create_stream_result = prepared.allow_stream_result && allow_stream_result;
101189
+ if (create_stream_result) {
101190
+ active_query->progress_bar.reset();
101191
+ query_progress = -1;
101192
+
101193
+ // successfully compiled SELECT clause and it is the last statement
101194
+ // return a StreamQueryResult so the client can call Fetch() on it and stream the result
101195
+ auto stream_result =
101196
+ make_unique<StreamQueryResult>(pending.statement_type, shared_from_this(), pending.types, pending.names);
101197
+ active_query->open_result = stream_result.get();
101198
+ return move(stream_result);
101199
+ }
101200
+ // create a materialized result by continuously fetching
101201
+ auto result = make_unique<MaterializedQueryResult>(pending.statement_type, pending.types, pending.names);
101202
+ while (true) {
101203
+ auto chunk = FetchInternal(lock, GetExecutor(), *result);
101204
+ if (!chunk || chunk->size() == 0) {
101205
+ break;
101206
+ }
101207
+ #ifdef DEBUG
101208
+ for (idx_t i = 0; i < chunk->ColumnCount(); i++) {
101209
+ if (pending.types[i].id() == LogicalTypeId::VARCHAR) {
101210
+ chunk->data[i].UTFVerify(chunk->size());
101211
+ }
101212
+ }
101213
+ #endif
101214
+ result->collection.Append(*chunk);
101215
+ }
101216
+ return move(result);
101009
101217
  }
101010
101218
 
101011
101219
  shared_ptr<PreparedStatementData> ClientContext::CreatePreparedStatement(ClientContextLock &lock, const string &query,
@@ -101013,11 +101221,12 @@ shared_ptr<PreparedStatementData> ClientContext::CreatePreparedStatement(ClientC
101013
101221
  StatementType statement_type = statement->type;
101014
101222
  auto result = make_shared<PreparedStatementData>(statement_type);
101015
101223
 
101016
- profiler->StartPhase("planner");
101224
+ auto &profiler = QueryProfiler::Get(*this);
101225
+ profiler.StartPhase("planner");
101017
101226
  Planner planner(*this);
101018
101227
  planner.CreatePlan(move(statement));
101019
101228
  D_ASSERT(planner.plan);
101020
- profiler->EndPhase();
101229
+ profiler.EndPhase();
101021
101230
 
101022
101231
  auto plan = move(planner.plan);
101023
101232
  #ifdef DEBUG
@@ -101033,22 +101242,22 @@ shared_ptr<PreparedStatementData> ClientContext::CreatePreparedStatement(ClientC
101033
101242
  result->catalog_version = Transaction::GetTransaction(*this).catalog_version;
101034
101243
 
101035
101244
  if (config.enable_optimizer) {
101036
- profiler->StartPhase("optimizer");
101245
+ profiler.StartPhase("optimizer");
101037
101246
  Optimizer optimizer(*planner.binder, *this);
101038
101247
  plan = optimizer.Optimize(move(plan));
101039
101248
  D_ASSERT(plan);
101040
- profiler->EndPhase();
101249
+ profiler.EndPhase();
101041
101250
 
101042
101251
  #ifdef DEBUG
101043
101252
  plan->Verify();
101044
101253
  #endif
101045
101254
  }
101046
101255
 
101047
- profiler->StartPhase("physical_planner");
101256
+ profiler.StartPhase("physical_planner");
101048
101257
  // now convert logical query plan into a physical query plan
101049
101258
  PhysicalPlanGenerator physical_planner(*this);
101050
101259
  auto physical_plan = physical_planner.CreatePlan(move(plan));
101051
- profiler->EndPhase();
101260
+ profiler.EndPhase();
101052
101261
 
101053
101262
  #ifdef DEBUG
101054
101263
  D_ASSERT(!physical_plan->ToString().empty());
@@ -101057,14 +101266,14 @@ shared_ptr<PreparedStatementData> ClientContext::CreatePreparedStatement(ClientC
101057
101266
  return result;
101058
101267
  }
101059
101268
 
101060
- int ClientContext::GetProgress() {
101061
- D_ASSERT(progress_bar);
101062
- return progress_bar->GetCurrentPercentage();
101269
+ double ClientContext::GetProgress() {
101270
+ return query_progress.load();
101063
101271
  }
101064
101272
 
101065
- unique_ptr<QueryResult> ClientContext::ExecutePreparedStatement(ClientContextLock &lock, const string &query,
101066
- shared_ptr<PreparedStatementData> statement_p,
101067
- vector<Value> bound_values, bool allow_stream_result) {
101273
+ unique_ptr<PendingQueryResult> ClientContext::PendingPreparedStatement(ClientContextLock &lock,
101274
+ shared_ptr<PreparedStatementData> statement_p,
101275
+ vector<Value> bound_values) {
101276
+ D_ASSERT(active_query);
101068
101277
  auto &statement = *statement_p;
101069
101278
  if (ActiveTransaction().IsInvalidated() && statement.requires_valid_transaction) {
101070
101279
  throw Exception("Current transaction is aborted (please ROLLBACK)");
@@ -101078,47 +101287,42 @@ unique_ptr<QueryResult> ClientContext::ExecutePreparedStatement(ClientContextLoc
101078
101287
  // bind the bound values before execution
101079
101288
  statement.Bind(move(bound_values));
101080
101289
 
101081
- bool create_stream_result = statement.allow_stream_result && allow_stream_result;
101290
+ active_query->executor = make_unique<Executor>(*this);
101291
+ auto &executor = *active_query->executor;
101082
101292
  if (config.enable_progress_bar) {
101083
- progress_bar->Initialize(config.wait_time);
101084
- progress_bar->Start();
101293
+ active_query->progress_bar = make_unique<ProgressBar>(executor, config.wait_time);
101294
+ active_query->progress_bar->Start();
101295
+ query_progress = 0;
101085
101296
  }
101086
- // store the physical plan in the context for calls to Fetch()
101087
101297
  executor.Initialize(statement.plan.get());
101088
-
101089
101298
  auto types = executor.GetTypes();
101090
-
101091
101299
  D_ASSERT(types == statement.types);
101300
+ D_ASSERT(!active_query->open_result);
101092
101301
 
101093
- if (create_stream_result) {
101094
- if (config.enable_progress_bar) {
101095
- progress_bar->Stop();
101096
- }
101097
- // successfully compiled SELECT clause and it is the last statement
101098
- // return a StreamQueryResult so the client can call Fetch() on it and stream the result
101099
- return make_unique<StreamQueryResult>(statement.statement_type, shared_from_this(), statement.types,
101100
- statement.names, move(statement_p));
101101
- }
101102
- // create a materialized result by continuously fetching
101103
- auto result = make_unique<MaterializedQueryResult>(statement.statement_type, statement.types, statement.names);
101104
- while (true) {
101105
- auto chunk = FetchInternal(lock);
101106
- if (chunk->size() == 0) {
101107
- break;
101108
- }
101109
- #ifdef DEBUG
101110
- for (idx_t i = 0; i < chunk->ColumnCount(); i++) {
101111
- if (statement.types[i].id() == LogicalTypeId::VARCHAR) {
101112
- chunk->data[i].UTFVerify(chunk->size());
101113
- }
101302
+ auto pending_result = make_unique<PendingQueryResult>(shared_from_this(), *statement_p, move(types));
101303
+ active_query->prepared = move(statement_p);
101304
+ active_query->open_result = pending_result.get();
101305
+ return pending_result;
101306
+ }
101307
+
101308
+ PendingExecutionResult ClientContext::ExecuteTaskInternal(ClientContextLock &lock, PendingQueryResult &result) {
101309
+ D_ASSERT(active_query);
101310
+ D_ASSERT(active_query->open_result == &result);
101311
+ try {
101312
+ auto result = active_query->executor->ExecuteTask();
101313
+ if (active_query->progress_bar) {
101314
+ active_query->progress_bar->Update(result == PendingExecutionResult::RESULT_READY);
101315
+ query_progress = active_query->progress_bar->GetCurrentPercentage();
101114
101316
  }
101115
- #endif
101116
- result->collection.Append(*chunk);
101117
- }
101118
- if (config.enable_progress_bar) {
101119
- progress_bar->Stop();
101120
- }
101121
- return move(result);
101317
+ return result;
101318
+ } catch (std::exception &ex) {
101319
+ result.error = ex.what();
101320
+ } catch (...) { // LCOV_EXCL_START
101321
+ result.error = "Unhandled exception in ExecuteTaskInternal";
101322
+ } // LCOV_EXCL_STOP
101323
+ EndQueryInternal(lock, false, true);
101324
+ result.success = false;
101325
+ return PendingExecutionResult::EXECUTION_ERROR;
101122
101326
  }
101123
101327
 
101124
101328
  void ClientContext::InitialCleanup(ClientContextLock &lock) {
@@ -101221,27 +101425,58 @@ unique_ptr<PreparedStatement> ClientContext::Prepare(const string &query) {
101221
101425
  }
101222
101426
  }
101223
101427
 
101428
+ unique_ptr<PendingQueryResult> ClientContext::PendingQueryPreparedInternal(ClientContextLock &lock, const string &query,
101429
+ shared_ptr<PreparedStatementData> &prepared,
101430
+ vector<Value> &values) {
101431
+ try {
101432
+ InitialCleanup(lock);
101433
+ } catch (std::exception &ex) {
101434
+ return make_unique<PendingQueryResult>(ex.what());
101435
+ }
101436
+ return PendingStatementOrPreparedStatementInternal(lock, query, nullptr, prepared, &values);
101437
+ }
101438
+
101439
+ unique_ptr<PendingQueryResult>
101440
+ ClientContext::PendingQuery(const string &query, shared_ptr<PreparedStatementData> &prepared, vector<Value> &values) {
101441
+ auto lock = LockContext();
101442
+ return PendingQueryPreparedInternal(*lock, query, prepared, values);
101443
+ }
101444
+
101224
101445
  unique_ptr<QueryResult> ClientContext::Execute(const string &query, shared_ptr<PreparedStatementData> &prepared,
101225
101446
  vector<Value> &values, bool allow_stream_result) {
101226
101447
  auto lock = LockContext();
101227
- try {
101228
- InitialCleanup(*lock);
101229
- } catch (std::exception &ex) {
101230
- return make_unique<MaterializedQueryResult>(ex.what());
101448
+ auto pending = PendingQueryPreparedInternal(*lock, query, prepared, values);
101449
+ if (!pending->success) {
101450
+ return make_unique<MaterializedQueryResult>(pending->error);
101231
101451
  }
101232
- LogQueryInternal(*lock, query);
101233
- return RunStatementOrPreparedStatement(*lock, query, nullptr, prepared, &values, allow_stream_result);
101452
+ return pending->ExecuteInternal(*lock, allow_stream_result);
101234
101453
  }
101235
101454
 
101236
- unique_ptr<QueryResult> ClientContext::RunStatementInternal(ClientContextLock &lock, const string &query,
101237
- unique_ptr<SQLStatement> statement,
101238
- bool allow_stream_result) {
101455
+ unique_ptr<PendingQueryResult> ClientContext::PendingStatementInternal(ClientContextLock &lock, const string &query,
101456
+ unique_ptr<SQLStatement> statement) {
101239
101457
  // prepare the query for execution
101240
101458
  auto prepared = CreatePreparedStatement(lock, query, move(statement));
101241
101459
  // by default, no values are bound
101242
101460
  vector<Value> bound_values;
101243
101461
  // execute the prepared statement
101244
- return ExecutePreparedStatement(lock, query, move(prepared), move(bound_values), allow_stream_result);
101462
+ return PendingPreparedStatement(lock, move(prepared), move(bound_values));
101463
+ }
101464
+
101465
+ unique_ptr<QueryResult> ClientContext::RunStatementInternal(ClientContextLock &lock, const string &query,
101466
+ unique_ptr<SQLStatement> statement,
101467
+ bool allow_stream_result, bool verify) {
101468
+ auto pending = PendingQueryInternal(lock, move(statement), verify);
101469
+ if (!pending->success) {
101470
+ return make_unique<MaterializedQueryResult>(move(pending->error));
101471
+ }
101472
+ return ExecutePendingQueryInternal(lock, *pending, allow_stream_result);
101473
+ }
101474
+
101475
+ bool ClientContext::IsActiveResult(ClientContextLock &lock, BaseQueryResult *result) {
101476
+ if (!active_query) {
101477
+ return false;
101478
+ }
101479
+ return active_query->open_result == result;
101245
101480
  }
101246
101481
 
101247
101482
  static bool IsExplainAnalyze(SQLStatement *statement) {
@@ -101255,19 +101490,10 @@ static bool IsExplainAnalyze(SQLStatement *statement) {
101255
101490
  return explain.explain_type == ExplainType::EXPLAIN_ANALYZE;
101256
101491
  }
101257
101492
 
101258
- unique_ptr<QueryResult> ClientContext::RunStatementOrPreparedStatement(ClientContextLock &lock, const string &query,
101259
- unique_ptr<SQLStatement> statement,
101260
- shared_ptr<PreparedStatementData> &prepared,
101261
- vector<Value> *values,
101262
- bool allow_stream_result) {
101263
- this->query = query;
101264
-
101265
- unique_ptr<QueryResult> result;
101493
+ unique_ptr<PendingQueryResult> ClientContext::PendingStatementOrPreparedStatementInternal(
101494
+ ClientContextLock &lock, const string &query, unique_ptr<SQLStatement> statement,
101495
+ shared_ptr<PreparedStatementData> &prepared, vector<Value> *values) {
101266
101496
  // check if we are on AutoCommit. In this case we should start a transaction.
101267
- if (transaction.IsAutoCommit()) {
101268
- transaction.BeginTransaction();
101269
- }
101270
- ActiveTransaction().active_query = db->GetTransactionManager().GetQueryNumber();
101271
101497
  if (statement && config.query_verification_enabled) {
101272
101498
  // query verification is enabled
101273
101499
  // create a copy of the statement, and use the copy
@@ -101277,19 +101503,29 @@ unique_ptr<QueryResult> ClientContext::RunStatementOrPreparedStatement(ClientCon
101277
101503
  // in case this is a select query, we verify the original statement
101278
101504
  string error = VerifyQuery(lock, query, move(statement));
101279
101505
  if (!error.empty()) {
101280
- // query failed: abort now
101281
- FinalizeQuery(lock, false);
101282
101506
  // error in verifying query
101283
- return make_unique<MaterializedQueryResult>(error);
101507
+ return make_unique<PendingQueryResult>(error);
101284
101508
  }
101285
101509
  }
101286
101510
  statement = move(copied_statement);
101287
101511
  }
101512
+ return PendingStatementOrPreparedStatement(lock, query, move(statement), prepared, values);
101513
+ }
101514
+
101515
+ unique_ptr<PendingQueryResult>
101516
+ ClientContext::PendingStatementOrPreparedStatement(ClientContextLock &lock, const string &query,
101517
+ unique_ptr<SQLStatement> statement,
101518
+ shared_ptr<PreparedStatementData> &prepared, vector<Value> *values) {
101519
+ unique_ptr<PendingQueryResult> result;
101520
+
101521
+ BeginQueryInternal(lock, query);
101288
101522
  // start the profiler
101289
- profiler->StartQuery(query, IsExplainAnalyze(statement ? statement.get() : prepared->unbound_statement.get()));
101523
+ auto &profiler = QueryProfiler::Get(*this);
101524
+ profiler.StartQuery(query, IsExplainAnalyze(statement ? statement.get() : prepared->unbound_statement.get()));
101525
+ bool invalidate_query = true;
101290
101526
  try {
101291
101527
  if (statement) {
101292
- result = RunStatementInternal(lock, query, move(statement), allow_stream_result);
101528
+ result = PendingStatementInternal(lock, query, move(statement));
101293
101529
  } else {
101294
101530
  auto &catalog = Catalog::GetCatalog(*this);
101295
101531
  if (prepared->unbound_statement && catalog.GetCatalogVersion() != prepared->catalog_version) {
@@ -101302,68 +101538,22 @@ unique_ptr<QueryResult> ClientContext::RunStatementOrPreparedStatement(ClientCon
101302
101538
  new_prepared->unbound_statement = move(prepared->unbound_statement);
101303
101539
  prepared = move(new_prepared);
101304
101540
  }
101305
- result = ExecutePreparedStatement(lock, query, prepared, *values, allow_stream_result);
101541
+ result = PendingPreparedStatement(lock, prepared, *values);
101306
101542
  }
101307
101543
  } catch (StandardException &ex) {
101308
101544
  // standard exceptions do not invalidate the current transaction
101309
- result = make_unique<MaterializedQueryResult>(ex.what());
101545
+ result = make_unique<PendingQueryResult>(ex.what());
101546
+ invalidate_query = false;
101310
101547
  } catch (std::exception &ex) {
101311
101548
  // other types of exceptions do invalidate the current transaction
101312
- if (transaction.HasActiveTransaction()) {
101313
- ActiveTransaction().Invalidate();
101314
- }
101315
- result = make_unique<MaterializedQueryResult>(ex.what());
101549
+ result = make_unique<PendingQueryResult>(ex.what());
101316
101550
  }
101317
101551
  if (!result->success) {
101318
- // initial failures should always be reported as MaterializedResult
101319
- D_ASSERT(result->type != QueryResultType::STREAM_RESULT);
101320
101552
  // query failed: abort now
101321
- FinalizeQuery(lock, false);
101553
+ EndQueryInternal(lock, false, invalidate_query);
101322
101554
  return result;
101323
101555
  }
101324
- // query succeeded, append to list of results
101325
- if (result->type == QueryResultType::STREAM_RESULT) {
101326
- // store as currently open result if it is a stream result
101327
- this->open_result = (StreamQueryResult *)result.get();
101328
- } else {
101329
- // finalize the query if it is not a stream result
101330
- string error = FinalizeQuery(lock, true);
101331
- if (!error.empty()) {
101332
- // failure in committing transaction
101333
- return make_unique<MaterializedQueryResult>(error);
101334
- }
101335
- }
101336
- return result;
101337
- }
101338
-
101339
- unique_ptr<QueryResult> ClientContext::RunStatement(ClientContextLock &lock, const string &query,
101340
- unique_ptr<SQLStatement> statement, bool allow_stream_result) {
101341
- shared_ptr<PreparedStatementData> prepared;
101342
- return RunStatementOrPreparedStatement(lock, query, move(statement), prepared, nullptr, allow_stream_result);
101343
- }
101344
-
101345
- unique_ptr<QueryResult> ClientContext::RunStatements(ClientContextLock &lock, const string &query,
101346
- vector<unique_ptr<SQLStatement>> &statements,
101347
- bool allow_stream_result) {
101348
- // now we have a list of statements
101349
- // iterate over them and execute them one by one
101350
- unique_ptr<QueryResult> result;
101351
- QueryResult *last_result = nullptr;
101352
- for (idx_t i = 0; i < statements.size(); i++) {
101353
- auto &statement = statements[i];
101354
- bool is_last_statement = i + 1 == statements.size();
101355
- auto current_result = RunStatement(lock, query, move(statement), allow_stream_result && is_last_statement);
101356
- // now append the result to the list of results
101357
- if (!last_result) {
101358
- // first result of the query
101359
- result = move(current_result);
101360
- last_result = result.get();
101361
- } else {
101362
- // later results; attach to the result chain
101363
- last_result->next = move(current_result);
101364
- last_result = last_result->next.get();
101365
- }
101366
- }
101556
+ D_ASSERT(active_query->open_result == result.get());
101367
101557
  return result;
101368
101558
  }
101369
101559
 
@@ -101389,34 +101579,96 @@ void ClientContext::LogQueryInternal(ClientContextLock &, const string &query) {
101389
101579
  }
101390
101580
 
101391
101581
  unique_ptr<QueryResult> ClientContext::Query(unique_ptr<SQLStatement> statement, bool allow_stream_result) {
101392
- auto lock = LockContext();
101393
- LogQueryInternal(*lock, statement->query.substr(statement->stmt_location, statement->stmt_length));
101394
-
101395
- vector<unique_ptr<SQLStatement>> statements;
101396
- statements.push_back(move(statement));
101397
-
101398
- return RunStatements(*lock, query, statements, allow_stream_result);
101582
+ auto pending_query = PendingQuery(move(statement));
101583
+ return pending_query->Execute(allow_stream_result);
101399
101584
  }
101400
101585
 
101401
101586
  unique_ptr<QueryResult> ClientContext::Query(const string &query, bool allow_stream_result) {
101402
101587
  auto lock = LockContext();
101403
- LogQueryInternal(*lock, query);
101404
101588
 
101589
+ string error;
101405
101590
  vector<unique_ptr<SQLStatement>> statements;
101591
+ if (!ParseStatements(*lock, query, statements, error)) {
101592
+ return make_unique<MaterializedQueryResult>(move(error));
101593
+ }
101594
+ if (statements.empty()) {
101595
+ // no statements, return empty successful result
101596
+ return make_unique<MaterializedQueryResult>(StatementType::INVALID_STATEMENT);
101597
+ }
101598
+
101599
+ unique_ptr<QueryResult> result;
101600
+ QueryResult *last_result = nullptr;
101601
+ for (idx_t i = 0; i < statements.size(); i++) {
101602
+ auto &statement = statements[i];
101603
+ bool is_last_statement = i + 1 == statements.size();
101604
+ bool stream_result = allow_stream_result && is_last_statement;
101605
+ auto pending_query = PendingQueryInternal(*lock, move(statement));
101606
+ unique_ptr<QueryResult> current_result;
101607
+ if (!pending_query->success) {
101608
+ current_result = make_unique<MaterializedQueryResult>(pending_query->error);
101609
+ } else {
101610
+ current_result = ExecutePendingQueryInternal(*lock, *pending_query, stream_result);
101611
+ }
101612
+ // now append the result to the list of results
101613
+ if (!last_result) {
101614
+ // first result of the query
101615
+ result = move(current_result);
101616
+ last_result = result.get();
101617
+ } else {
101618
+ // later results; attach to the result chain
101619
+ last_result->next = move(current_result);
101620
+ last_result = last_result->next.get();
101621
+ }
101622
+ }
101623
+ return result;
101624
+ }
101625
+
101626
+ bool ClientContext::ParseStatements(ClientContextLock &lock, const string &query,
101627
+ vector<unique_ptr<SQLStatement>> &result, string &error) {
101406
101628
  try {
101407
- InitialCleanup(*lock);
101629
+ InitialCleanup(lock);
101408
101630
  // parse the query and transform it into a set of statements
101409
- statements = ParseStatementsInternal(*lock, query);
101631
+ result = ParseStatementsInternal(lock, query);
101632
+ return true;
101410
101633
  } catch (std::exception &ex) {
101411
- return make_unique<MaterializedQueryResult>(ex.what());
101634
+ error = ex.what();
101635
+ return false;
101412
101636
  }
101637
+ }
101413
101638
 
101414
- if (statements.empty()) {
101415
- // no statements, return empty successful result
101416
- return make_unique<MaterializedQueryResult>(StatementType::INVALID_STATEMENT);
101639
+ unique_ptr<PendingQueryResult> ClientContext::PendingQuery(const string &query) {
101640
+ auto lock = LockContext();
101641
+
101642
+ string error;
101643
+ vector<unique_ptr<SQLStatement>> statements;
101644
+ if (!ParseStatements(*lock, query, statements, error)) {
101645
+ return make_unique<PendingQueryResult>(move(error));
101417
101646
  }
101647
+ if (statements.size() != 1) {
101648
+ return make_unique<PendingQueryResult>("PendingQuery can only take a single statement");
101649
+ }
101650
+ return PendingQueryInternal(*lock, move(statements[0]));
101651
+ }
101418
101652
 
101419
- return RunStatements(*lock, query, statements, allow_stream_result);
101653
+ unique_ptr<PendingQueryResult> ClientContext::PendingQuery(unique_ptr<SQLStatement> statement) {
101654
+ auto lock = LockContext();
101655
+ return PendingQueryInternal(*lock, move(statement));
101656
+ }
101657
+
101658
+ unique_ptr<PendingQueryResult> ClientContext::PendingQueryInternal(ClientContextLock &lock,
101659
+ unique_ptr<SQLStatement> statement, bool verify) {
101660
+ auto query = statement->query;
101661
+ shared_ptr<PreparedStatementData> prepared;
101662
+ if (verify) {
101663
+ return PendingStatementOrPreparedStatementInternal(lock, query, move(statement), prepared, nullptr);
101664
+ } else {
101665
+ return PendingStatementOrPreparedStatement(lock, query, move(statement), prepared, nullptr);
101666
+ }
101667
+ }
101668
+
101669
+ unique_ptr<QueryResult> ClientContext::ExecutePendingQueryInternal(ClientContextLock &lock, PendingQueryResult &query,
101670
+ bool allow_stream_result) {
101671
+ return query.ExecuteInternal(lock, allow_stream_result);
101420
101672
  }
101421
101673
 
101422
101674
  void ClientContext::Interrupt() {
@@ -101425,12 +101677,14 @@ void ClientContext::Interrupt() {
101425
101677
 
101426
101678
  void ClientContext::EnableProfiling() {
101427
101679
  auto lock = LockContext();
101428
- profiler->Enable();
101680
+ auto &config = ClientConfig::GetConfig(*this);
101681
+ config.enable_profiler = true;
101429
101682
  }
101430
101683
 
101431
101684
  void ClientContext::DisableProfiling() {
101432
101685
  auto lock = LockContext();
101433
- profiler->Disable();
101686
+ auto &config = ClientConfig::GetConfig(*this);
101687
+ config.enable_profiler = false;
101434
101688
  }
101435
101689
 
101436
101690
  string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query, unique_ptr<SQLStatement> statement) {
@@ -101492,9 +101746,10 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
101492
101746
  #endif
101493
101747
 
101494
101748
  // disable profiling if it is enabled
101495
- bool profiling_is_enabled = profiler->IsEnabled();
101749
+ auto &config = ClientConfig::GetConfig(*this);
101750
+ bool profiling_is_enabled = config.enable_profiler;
101496
101751
  if (profiling_is_enabled) {
101497
- profiler->Disable();
101752
+ config.enable_profiler = false;
101498
101753
  }
101499
101754
 
101500
101755
  // see below
@@ -101511,7 +101766,7 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
101511
101766
 
101512
101767
  // execute the original statement
101513
101768
  try {
101514
- auto result = RunStatementInternal(lock, query, move(statement), false);
101769
+ auto result = RunStatementInternal(lock, query, move(statement), false, false);
101515
101770
  original_result = unique_ptr_cast<QueryResult, MaterializedQueryResult>(move(result));
101516
101771
  } catch (std::exception &ex) {
101517
101772
  original_result->error = ex.what();
@@ -101524,7 +101779,7 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
101524
101779
  auto explain_q = "EXPLAIN " + query;
101525
101780
  auto explain_stmt = make_unique<ExplainStatement>(move(statement_copy_for_explain));
101526
101781
  try {
101527
- RunStatementInternal(lock, explain_q, move(explain_stmt), false);
101782
+ RunStatementInternal(lock, explain_q, move(explain_stmt), false, false);
101528
101783
  } catch (std::exception &ex) { // LCOV_EXCL_START
101529
101784
  return "EXPLAIN failed but query did not (" + string(ex.what()) + ")";
101530
101785
  } // LCOV_EXCL_STOP
@@ -101532,7 +101787,7 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
101532
101787
 
101533
101788
  // now execute the copied statement
101534
101789
  try {
101535
- auto result = RunStatementInternal(lock, query, move(copied_stmt), false);
101790
+ auto result = RunStatementInternal(lock, query, move(copied_stmt), false, false);
101536
101791
  copied_result = unique_ptr_cast<QueryResult, MaterializedQueryResult>(move(result));
101537
101792
  } catch (std::exception &ex) {
101538
101793
  copied_result->error = ex.what();
@@ -101541,7 +101796,7 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
101541
101796
  }
101542
101797
  // now execute the deserialized statement
101543
101798
  try {
101544
- auto result = RunStatementInternal(lock, query, move(deserialized_stmt), false);
101799
+ auto result = RunStatementInternal(lock, query, move(deserialized_stmt), false, false);
101545
101800
  deserialized_result = unique_ptr_cast<QueryResult, MaterializedQueryResult>(move(result));
101546
101801
  } catch (std::exception &ex) {
101547
101802
  deserialized_result->error = ex.what();
@@ -101551,7 +101806,7 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
101551
101806
  // now execute the unoptimized statement
101552
101807
  config.enable_optimizer = false;
101553
101808
  try {
101554
- auto result = RunStatementInternal(lock, query, move(unoptimized_stmt), false);
101809
+ auto result = RunStatementInternal(lock, query, move(unoptimized_stmt), false, false);
101555
101810
  unoptimized_result = unique_ptr_cast<QueryResult, MaterializedQueryResult>(move(result));
101556
101811
  } catch (std::exception &ex) {
101557
101812
  unoptimized_result->error = ex.what();
@@ -101561,7 +101816,7 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
101561
101816
  config.enable_optimizer = true;
101562
101817
 
101563
101818
  if (profiling_is_enabled) {
101564
- profiler->Enable();
101819
+ config.enable_profiler = true;
101565
101820
  }
101566
101821
 
101567
101822
  // now compare the results
@@ -101615,7 +101870,7 @@ bool ClientContext::UpdateFunctionInfoFromEntry(ScalarFunctionCatalogEntry *exis
101615
101870
  void ClientContext::RegisterFunction(CreateFunctionInfo *info) {
101616
101871
  RunFunctionInTransaction([&]() {
101617
101872
  auto &catalog = Catalog::GetCatalog(*this);
101618
- ScalarFunctionCatalogEntry *existing_function = (ScalarFunctionCatalogEntry *)catalog.GetEntry(
101873
+ auto existing_function = (ScalarFunctionCatalogEntry *)catalog.GetEntry(
101619
101874
  *this, CatalogType::SCALAR_FUNCTION_ENTRY, info->schema, info->name, true);
101620
101875
  if (existing_function) {
101621
101876
  if (UpdateFunctionInfoFromEntry(existing_function, (CreateScalarFunctionInfo *)info)) {
@@ -101637,6 +101892,7 @@ void ClientContext::RunFunctionInTransactionInternal(ClientContextLock &lock, co
101637
101892
  // check if we are on AutoCommit. In this case we should start a transaction
101638
101893
  bool require_new_transaction = transaction.IsAutoCommit() && !transaction.HasActiveTransaction();
101639
101894
  if (require_new_transaction) {
101895
+ D_ASSERT(!active_query);
101640
101896
  transaction.BeginTransaction();
101641
101897
  }
101642
101898
  try {
@@ -101751,12 +102007,14 @@ unique_ptr<QueryResult> ClientContext::Execute(const shared_ptr<Relation> &relat
101751
102007
  // verify read only statements by running a select statement
101752
102008
  auto select = make_unique<SelectStatement>();
101753
102009
  select->node = relation->GetQueryNode();
101754
- RunStatement(*lock, query, move(select), false);
102010
+ RunStatementInternal(*lock, query, move(select), false);
101755
102011
  }
101756
102012
  }
101757
102013
  auto &expected_columns = relation->Columns();
101758
102014
  auto relation_stmt = make_unique<RelationStatement>(relation);
101759
- auto result = RunStatement(*lock, query, move(relation_stmt), false);
102015
+
102016
+ unique_ptr<QueryResult> result;
102017
+ result = RunStatementInternal(*lock, query, move(relation_stmt), false);
101760
102018
  if (!result->success) {
101761
102019
  return result;
101762
102020
  }
@@ -102528,10 +102786,11 @@ Connection::Connection(DuckDB &database) : Connection(*database.instance) {
102528
102786
  }
102529
102787
 
102530
102788
  string Connection::GetProfilingInformation(ProfilerPrintFormat format) {
102789
+ auto &profiler = QueryProfiler::Get(*context);
102531
102790
  if (format == ProfilerPrintFormat::JSON) {
102532
- return context->profiler->ToJSON();
102791
+ return profiler.ToJSON();
102533
102792
  } else {
102534
- return context->profiler->ToString();
102793
+ return profiler.ToString();
102535
102794
  }
102536
102795
  }
102537
102796
 
@@ -102575,6 +102834,14 @@ unique_ptr<MaterializedQueryResult> Connection::Query(unique_ptr<SQLStatement> s
102575
102834
  return unique_ptr_cast<QueryResult, MaterializedQueryResult>(move(result));
102576
102835
  }
102577
102836
 
102837
+ unique_ptr<PendingQueryResult> Connection::PendingQuery(const string &query) {
102838
+ return context->PendingQuery(query);
102839
+ }
102840
+
102841
+ unique_ptr<PendingQueryResult> Connection::PendingQuery(unique_ptr<SQLStatement> statement) {
102842
+ return context->PendingQuery(move(statement));
102843
+ }
102844
+
102578
102845
  unique_ptr<PreparedStatement> Connection::Prepare(const string &query) {
102579
102846
  return context->Prepare(query);
102580
102847
  }
@@ -110883,6 +111150,75 @@ unique_ptr<DataChunk> MaterializedQueryResult::FetchRaw() {
110883
111150
 
110884
111151
 
110885
111152
 
111153
+ namespace duckdb {
111154
+
111155
+ PendingQueryResult::PendingQueryResult(shared_ptr<ClientContext> context_p, PreparedStatementData &statement,
111156
+ vector<LogicalType> types_p)
111157
+ : BaseQueryResult(QueryResultType::PENDING_RESULT, statement.statement_type, move(types_p), statement.names),
111158
+ context(move(context_p)) {
111159
+ }
111160
+
111161
+ PendingQueryResult::PendingQueryResult(string error) : BaseQueryResult(QueryResultType::PENDING_RESULT, move(error)) {
111162
+ }
111163
+
111164
+ PendingQueryResult::~PendingQueryResult() {
111165
+ }
111166
+
111167
+ unique_ptr<ClientContextLock> PendingQueryResult::LockContext() {
111168
+ if (!context) {
111169
+ throw InvalidInputException("Attempting to execute an unsuccessful or closed pending query result\nError: %s",
111170
+ error);
111171
+ }
111172
+ return context->LockContext();
111173
+ }
111174
+
111175
+ void PendingQueryResult::CheckExecutableInternal(ClientContextLock &lock) {
111176
+ bool invalidated = !success || !context;
111177
+ if (!invalidated) {
111178
+ invalidated = !context->IsActiveResult(lock, this);
111179
+ }
111180
+ if (invalidated) {
111181
+ throw InvalidInputException("Attempting to execute an unsuccessful or closed pending query result\nError: %s",
111182
+ error);
111183
+ }
111184
+ }
111185
+
111186
+ PendingExecutionResult PendingQueryResult::ExecuteTask() {
111187
+ auto lock = LockContext();
111188
+ return ExecuteTaskInternal(*lock);
111189
+ }
111190
+
111191
+ PendingExecutionResult PendingQueryResult::ExecuteTaskInternal(ClientContextLock &lock) {
111192
+ CheckExecutableInternal(lock);
111193
+ return context->ExecuteTaskInternal(lock, *this);
111194
+ }
111195
+
111196
+ unique_ptr<QueryResult> PendingQueryResult::ExecuteInternal(ClientContextLock &lock, bool allow_streaming_result) {
111197
+ CheckExecutableInternal(lock);
111198
+ while (ExecuteTaskInternal(lock) == PendingExecutionResult::RESULT_NOT_READY) {
111199
+ }
111200
+ if (!success) {
111201
+ return make_unique<MaterializedQueryResult>(error);
111202
+ }
111203
+ auto result = context->FetchResultInternal(lock, *this, allow_streaming_result);
111204
+ Close();
111205
+ return result;
111206
+ }
111207
+
111208
+ unique_ptr<QueryResult> PendingQueryResult::Execute(bool allow_streaming_result) {
111209
+ auto lock = LockContext();
111210
+ return ExecuteInternal(*lock, allow_streaming_result);
111211
+ }
111212
+
111213
+ void PendingQueryResult::Close() {
111214
+ context.reset();
111215
+ }
111216
+
111217
+ } // namespace duckdb
111218
+
111219
+
111220
+
111221
+
110886
111222
 
110887
111223
  namespace duckdb {
110888
111224
 
@@ -110919,11 +111255,19 @@ const vector<string> &PreparedStatement::GetNames() {
110919
111255
  }
110920
111256
 
110921
111257
  unique_ptr<QueryResult> PreparedStatement::Execute(vector<Value> &values, bool allow_stream_result) {
111258
+ auto pending = PendingQuery(values);
111259
+ if (!pending->success) {
111260
+ return make_unique<MaterializedQueryResult>(pending->error);
111261
+ }
111262
+ return pending->Execute(allow_stream_result && data->allow_stream_result);
111263
+ }
111264
+
111265
+ unique_ptr<PendingQueryResult> PreparedStatement::PendingQuery(vector<Value> &values) {
110922
111266
  if (!success) {
110923
111267
  throw InvalidInputException("Attempting to execute an unsuccessfully prepared statement!");
110924
111268
  }
110925
111269
  D_ASSERT(data);
110926
- auto result = context->Execute(query, data, values, allow_stream_result && data->allow_stream_result);
111270
+ auto result = context->PendingQuery(query, data, values);
110927
111271
  return result;
110928
111272
  }
110929
111273
 
@@ -111009,16 +111353,42 @@ using std::ofstream;
111009
111353
 
111010
111354
 
111011
111355
 
111356
+
111357
+
111012
111358
  #include <utility>
111013
111359
  #include <algorithm>
111014
111360
 
111015
111361
  namespace duckdb {
111016
111362
 
111363
+ QueryProfiler::QueryProfiler(ClientContext &context_p)
111364
+ : context(context_p), running(false), query_requires_profiling(false), is_explain_analyze(false) {
111365
+ }
111366
+
111367
+ bool QueryProfiler::IsEnabled() const {
111368
+ return is_explain_analyze ? true : ClientConfig::GetConfig(context).enable_profiler;
111369
+ }
111370
+
111371
+ bool QueryProfiler::IsDetailedEnabled() const {
111372
+ return is_explain_analyze ? false : ClientConfig::GetConfig(context).enable_detailed_profiling;
111373
+ }
111374
+
111375
+ ProfilerPrintFormat QueryProfiler::GetPrintFormat() const {
111376
+ return is_explain_analyze ? ProfilerPrintFormat::NONE : ClientConfig::GetConfig(context).profiler_print_format;
111377
+ }
111378
+
111379
+ string QueryProfiler::GetSaveLocation() const {
111380
+ return is_explain_analyze ? string() : ClientConfig::GetConfig(context).profiler_save_location;
111381
+ }
111382
+
111383
+ QueryProfiler &QueryProfiler::Get(ClientContext &context) {
111384
+ return *context.profiler;
111385
+ }
111386
+
111017
111387
  void QueryProfiler::StartQuery(string query, bool is_explain_analyze) {
111018
111388
  if (is_explain_analyze) {
111019
111389
  StartExplainAnalyze();
111020
111390
  }
111021
- if (!enabled) {
111391
+ if (!IsEnabled()) {
111022
111392
  return;
111023
111393
  }
111024
111394
  this->running = true;
@@ -111076,17 +111446,10 @@ void QueryProfiler::Finalize(TreeNode &node) {
111076
111446
 
111077
111447
  void QueryProfiler::StartExplainAnalyze() {
111078
111448
  this->is_explain_analyze = true;
111079
- this->stored_enabled = enabled;
111080
- this->stored_automatic_print_format = automatic_print_format;
111081
- this->stored_save_location = save_location;
111082
-
111083
- this->enabled = true;
111084
- this->save_location = string();
111085
- this->automatic_print_format = ProfilerPrintFormat::NONE;
111086
111449
  }
111087
111450
 
111088
111451
  void QueryProfiler::EndQuery() {
111089
- if (!enabled || !running) {
111452
+ if (!IsEnabled() || !running) {
111090
111453
  return;
111091
111454
  }
111092
111455
 
@@ -111095,6 +111458,7 @@ void QueryProfiler::EndQuery() {
111095
111458
  Finalize(*root);
111096
111459
  }
111097
111460
  this->running = false;
111461
+ auto automatic_print_format = GetPrintFormat();
111098
111462
  // print or output the query profiling after termination, if this is enabled
111099
111463
  if (automatic_print_format != ProfilerPrintFormat::NONE) {
111100
111464
  // check if this query should be output based on the operator types
@@ -111106,7 +111470,7 @@ void QueryProfiler::EndQuery() {
111106
111470
  } else if (automatic_print_format == ProfilerPrintFormat::QUERY_TREE_OPTIMIZER) {
111107
111471
  query_info = ToString(true);
111108
111472
  }
111109
-
111473
+ auto save_location = GetSaveLocation();
111110
111474
  if (save_location.empty()) {
111111
111475
  Printer::Print(query_info);
111112
111476
  Printer::Print("\n");
@@ -111114,16 +111478,11 @@ void QueryProfiler::EndQuery() {
111114
111478
  WriteToFile(save_location.c_str(), query_info);
111115
111479
  }
111116
111480
  }
111117
- if (is_explain_analyze) {
111118
- this->is_explain_analyze = false;
111119
- this->enabled = stored_enabled;
111120
- this->automatic_print_format = stored_automatic_print_format;
111121
- this->save_location = stored_save_location;
111122
- }
111481
+ this->is_explain_analyze = false;
111123
111482
  }
111124
111483
 
111125
111484
  void QueryProfiler::StartPhase(string new_phase) {
111126
- if (!enabled || !running) {
111485
+ if (!IsEnabled() || !running) {
111127
111486
  return;
111128
111487
  }
111129
111488
 
@@ -111147,7 +111506,7 @@ void QueryProfiler::StartPhase(string new_phase) {
111147
111506
  }
111148
111507
 
111149
111508
  void QueryProfiler::EndPhase() {
111150
- if (!enabled || !running) {
111509
+ if (!IsEnabled() || !running) {
111151
111510
  return;
111152
111511
  }
111153
111512
  D_ASSERT(phase_stack.size() > 0);
@@ -111167,7 +111526,7 @@ void QueryProfiler::EndPhase() {
111167
111526
  }
111168
111527
 
111169
111528
  void QueryProfiler::Initialize(PhysicalOperator *root_op) {
111170
- if (!enabled || !running) {
111529
+ if (!IsEnabled() || !running) {
111171
111530
  return;
111172
111531
  }
111173
111532
  this->query_requires_profiling = false;
@@ -111248,7 +111607,7 @@ void OperatorProfiler::Flush(const PhysicalOperator *phys_op, ExpressionExecutor
111248
111607
  }
111249
111608
 
111250
111609
  void QueryProfiler::Flush(OperatorProfiler &profiler) {
111251
- if (!enabled || !running) {
111610
+ if (!IsEnabled() || !running) {
111252
111611
  return;
111253
111612
  }
111254
111613
  lock_guard<mutex> guard(flush_lock);
@@ -111258,7 +111617,7 @@ void QueryProfiler::Flush(OperatorProfiler &profiler) {
111258
111617
 
111259
111618
  entry->second->info.time += node.second.time;
111260
111619
  entry->second->info.elements += node.second.elements;
111261
- if (!detailed_enabled) {
111620
+ if (!IsDetailedEnabled()) {
111262
111621
  continue;
111263
111622
  }
111264
111623
  for (auto &info : node.second.executors_info) {
@@ -111319,7 +111678,7 @@ string QueryProfiler::ToString(bool print_optimizer_output) const {
111319
111678
  }
111320
111679
 
111321
111680
  void QueryProfiler::ToStream(std::ostream &ss, bool print_optimizer_output) const {
111322
- if (!enabled) {
111681
+ if (!IsEnabled()) {
111323
111682
  ss << "Query profiling is disabled. Call "
111324
111683
  "Connection::EnableProfiling() to enable profiling!";
111325
111684
  return;
@@ -111490,7 +111849,7 @@ static void ToJSONRecursive(QueryProfiler::TreeNode &node, std::ostream &ss, int
111490
111849
  }
111491
111850
 
111492
111851
  string QueryProfiler::ToJSON() const {
111493
- if (!enabled) {
111852
+ if (!IsEnabled()) {
111494
111853
  return "{ \"result\": \"disabled\" }\n";
111495
111854
  }
111496
111855
  if (query.empty()) {
@@ -111605,10 +111964,6 @@ vector<QueryProfiler::PhaseTimingItem> QueryProfiler::GetOrderedPhaseTimings() c
111605
111964
  return result;
111606
111965
  }
111607
111966
  void QueryProfiler::Propagate(QueryProfiler &qp) {
111608
- this->automatic_print_format = qp.automatic_print_format;
111609
- this->save_location = qp.save_location;
111610
- this->enabled = qp.enabled;
111611
- this->detailed_enabled = qp.detailed_enabled;
111612
111967
  }
111613
111968
 
111614
111969
  void ExpressionInfo::ExtractExpressionsRecursive(unique_ptr<ExpressionState> &state) {
@@ -111665,17 +112020,44 @@ ExpressionRootInfo::ExpressionRootInfo(ExpressionExecutorState &state, string na
111665
112020
 
111666
112021
  namespace duckdb {
111667
112022
 
111668
- QueryResult::QueryResult(QueryResultType type, StatementType statement_type)
112023
+ BaseQueryResult::BaseQueryResult(QueryResultType type, StatementType statement_type)
111669
112024
  : type(type), statement_type(statement_type), success(true) {
111670
112025
  }
111671
112026
 
111672
- QueryResult::QueryResult(QueryResultType type, StatementType statement_type, vector<LogicalType> types_p,
111673
- vector<string> names_p)
112027
+ BaseQueryResult::BaseQueryResult(QueryResultType type, StatementType statement_type, vector<LogicalType> types_p,
112028
+ vector<string> names_p)
111674
112029
  : type(type), statement_type(statement_type), types(move(types_p)), names(move(names_p)), success(true) {
111675
112030
  D_ASSERT(types.size() == names.size());
111676
112031
  }
111677
112032
 
111678
- QueryResult::QueryResult(QueryResultType type, string error) : type(type), success(false), error(move(error)) {
112033
+ BaseQueryResult::BaseQueryResult(QueryResultType type, string error) : type(type), success(false), error(move(error)) {
112034
+ }
112035
+
112036
+ BaseQueryResult::~BaseQueryResult() {
112037
+ }
112038
+
112039
+ bool BaseQueryResult::HasError() {
112040
+ return !success;
112041
+ }
112042
+ const string &BaseQueryResult::GetError() {
112043
+ return error;
112044
+ }
112045
+ idx_t BaseQueryResult::ColumnCount() {
112046
+ return types.size();
112047
+ }
112048
+
112049
+ QueryResult::QueryResult(QueryResultType type, StatementType statement_type) : BaseQueryResult(type, statement_type) {
112050
+ }
112051
+
112052
+ QueryResult::QueryResult(QueryResultType type, StatementType statement_type, vector<LogicalType> types_p,
112053
+ vector<string> names_p)
112054
+ : BaseQueryResult(type, statement_type, move(types_p), move(names_p)) {
112055
+ }
112056
+
112057
+ QueryResult::QueryResult(QueryResultType type, string error) : BaseQueryResult(type, move(error)) {
112058
+ }
112059
+
112060
+ QueryResult::~QueryResult() {
111679
112061
  }
111680
112062
 
111681
112063
  unique_ptr<DataChunk> QueryResult::Fetch() {
@@ -114694,24 +115076,27 @@ Value EnableObjectCacheSetting::GetSetting(ClientContext &context) {
114694
115076
  //===--------------------------------------------------------------------===//
114695
115077
  void EnableProfilingSetting::SetLocal(ClientContext &context, const Value &input) {
114696
115078
  auto parameter = StringUtil::Lower(input.ToString());
115079
+
115080
+ auto &config = ClientConfig::GetConfig(context);
114697
115081
  if (parameter == "json") {
114698
- context.profiler->automatic_print_format = ProfilerPrintFormat::JSON;
115082
+ config.profiler_print_format = ProfilerPrintFormat::JSON;
114699
115083
  } else if (parameter == "query_tree") {
114700
- context.profiler->automatic_print_format = ProfilerPrintFormat::QUERY_TREE;
115084
+ config.profiler_print_format = ProfilerPrintFormat::QUERY_TREE;
114701
115085
  } else if (parameter == "query_tree_optimizer") {
114702
- context.profiler->automatic_print_format = ProfilerPrintFormat::QUERY_TREE_OPTIMIZER;
115086
+ config.profiler_print_format = ProfilerPrintFormat::QUERY_TREE_OPTIMIZER;
114703
115087
  } else {
114704
115088
  throw ParserException(
114705
115089
  "Unrecognized print format %s, supported formats: [json, query_tree, query_tree_optimizer]", parameter);
114706
115090
  }
114707
- context.profiler->Enable();
115091
+ config.enable_profiler = true;
114708
115092
  }
114709
115093
 
114710
115094
  Value EnableProfilingSetting::GetSetting(ClientContext &context) {
114711
- if (!context.profiler->IsEnabled()) {
115095
+ auto &config = ClientConfig::GetConfig(context);
115096
+ if (!config.enable_profiler) {
114712
115097
  return Value();
114713
115098
  }
114714
- switch (context.profiler->automatic_print_format) {
115099
+ switch (config.profiler_print_format) {
114715
115100
  case ProfilerPrintFormat::NONE:
114716
115101
  return Value("none");
114717
115102
  case ProfilerPrintFormat::JSON:
@@ -114855,12 +115240,14 @@ Value ProfilerHistorySize::GetSetting(ClientContext &context) {
114855
115240
  // Profile Output
114856
115241
  //===--------------------------------------------------------------------===//
114857
115242
  void ProfileOutputSetting::SetLocal(ClientContext &context, const Value &input) {
115243
+ auto &config = ClientConfig::GetConfig(context);
114858
115244
  auto parameter = input.ToString();
114859
- context.profiler->save_location = parameter;
115245
+ config.profiler_save_location = parameter;
114860
115246
  }
114861
115247
 
114862
115248
  Value ProfileOutputSetting::GetSetting(ClientContext &context) {
114863
- return Value(context.profiler->save_location);
115249
+ auto &config = ClientConfig::GetConfig(context);
115250
+ return Value(config.profiler_save_location);
114864
115251
  }
114865
115252
 
114866
115253
  //===--------------------------------------------------------------------===//
@@ -114868,17 +115255,24 @@ Value ProfileOutputSetting::GetSetting(ClientContext &context) {
114868
115255
  //===--------------------------------------------------------------------===//
114869
115256
  void ProfilingModeSetting::SetLocal(ClientContext &context, const Value &input) {
114870
115257
  auto parameter = StringUtil::Lower(input.ToString());
115258
+ auto &config = ClientConfig::GetConfig(context);
114871
115259
  if (parameter == "standard") {
114872
- context.profiler->Enable();
115260
+ config.enable_profiler = true;
115261
+ config.enable_detailed_profiling = false;
114873
115262
  } else if (parameter == "detailed") {
114874
- context.profiler->DetailedEnable();
115263
+ config.enable_profiler = true;
115264
+ config.enable_detailed_profiling = true;
114875
115265
  } else {
114876
115266
  throw ParserException("Unrecognized profiling mode \"%s\", supported formats: [standard, detailed]", parameter);
114877
115267
  }
114878
115268
  }
114879
115269
 
114880
115270
  Value ProfilingModeSetting::GetSetting(ClientContext &context) {
114881
- return Value(context.profiler->IsDetailedEnabled() ? "detailed" : "standard");
115271
+ auto &config = ClientConfig::GetConfig(context);
115272
+ if (!config.enable_profiler) {
115273
+ return Value();
115274
+ }
115275
+ return Value(config.enable_detailed_profiling ? "detailed" : "standard");
114882
115276
  }
114883
115277
 
114884
115278
  //===--------------------------------------------------------------------===//
@@ -114958,14 +115352,11 @@ Value ThreadsSetting::GetSetting(ClientContext &context) {
114958
115352
  namespace duckdb {
114959
115353
 
114960
115354
  StreamQueryResult::StreamQueryResult(StatementType statement_type, shared_ptr<ClientContext> context,
114961
- vector<LogicalType> types, vector<string> names,
114962
- shared_ptr<PreparedStatementData> prepared)
114963
- : QueryResult(QueryResultType::STREAM_RESULT, statement_type, move(types), move(names)), is_open(true),
114964
- context(move(context)), prepared(move(prepared)) {
115355
+ vector<LogicalType> types, vector<string> names)
115356
+ : QueryResult(QueryResultType::STREAM_RESULT, statement_type, move(types), move(names)), context(move(context)) {
114965
115357
  }
114966
115358
 
114967
115359
  StreamQueryResult::~StreamQueryResult() {
114968
- Close();
114969
115360
  }
114970
115361
 
114971
115362
  string StreamQueryResult::ToString() {
@@ -114979,12 +115370,28 @@ string StreamQueryResult::ToString() {
114979
115370
  return result;
114980
115371
  }
114981
115372
 
115373
+ unique_ptr<ClientContextLock> StreamQueryResult::LockContext() {
115374
+ if (!context) {
115375
+ throw InvalidInputException("Attempting to execute an unsuccessful or closed pending query result\nError: %s",
115376
+ error);
115377
+ }
115378
+ return context->LockContext();
115379
+ }
115380
+
115381
+ void StreamQueryResult::CheckExecutableInternal(ClientContextLock &lock) {
115382
+ if (!IsOpenInternal(lock)) {
115383
+ throw InvalidInputException("Attempting to execute an unsuccessful or closed pending query result\nError: %s",
115384
+ error);
115385
+ }
115386
+ }
115387
+
114982
115388
  unique_ptr<DataChunk> StreamQueryResult::FetchRaw() {
114983
- if (!success || !is_open) {
114984
- throw InvalidInputException(
114985
- "Attempting to fetch from an unsuccessful or closed streaming query result\nError: %s", error);
115389
+ unique_ptr<DataChunk> chunk;
115390
+ {
115391
+ auto lock = LockContext();
115392
+ CheckExecutableInternal(*lock);
115393
+ chunk = context->Fetch(*lock, *this);
114986
115394
  }
114987
- auto chunk = context->Fetch();
114988
115395
  if (!chunk || chunk->ColumnCount() == 0 || chunk->size() == 0) {
114989
115396
  Close();
114990
115397
  return nullptr;
@@ -115010,12 +115417,24 @@ unique_ptr<MaterializedQueryResult> StreamQueryResult::Materialize() {
115010
115417
  return result;
115011
115418
  }
115012
115419
 
115013
- void StreamQueryResult::Close() {
115014
- if (!is_open) {
115015
- return;
115420
+ bool StreamQueryResult::IsOpenInternal(ClientContextLock &lock) {
115421
+ bool invalidated = !success || !context;
115422
+ if (!invalidated) {
115423
+ invalidated = !context->IsActiveResult(lock, this);
115016
115424
  }
115017
- is_open = false;
115018
- context->Cleanup();
115425
+ return !invalidated;
115426
+ }
115427
+
115428
+ bool StreamQueryResult::IsOpen() {
115429
+ if (!success || !context) {
115430
+ return false;
115431
+ }
115432
+ auto lock = LockContext();
115433
+ return IsOpenInternal(*lock);
115434
+ }
115435
+
115436
+ void StreamQueryResult::Close() {
115437
+ context.reset();
115019
115438
  }
115020
115439
 
115021
115440
  } // namespace duckdb
@@ -119810,9 +120229,10 @@ void Optimizer::RunOptimizer(OptimizerType type, const std::function<void()> &ca
119810
120229
  // optimizer is marked as disabled: skip
119811
120230
  return;
119812
120231
  }
119813
- context.profiler->StartPhase(OptimizerTypeToString(type));
120232
+ auto &profiler = QueryProfiler::Get(context);
120233
+ profiler.StartPhase(OptimizerTypeToString(type));
119814
120234
  callback();
119815
- context.profiler->EndPhase();
120235
+ profiler.EndPhase();
119816
120236
  }
119817
120237
 
119818
120238
  unique_ptr<LogicalOperator> Optimizer::Optimize(unique_ptr<LogicalOperator> plan) {
@@ -123771,6 +124191,10 @@ public:
123771
124191
 
123772
124192
  //! Fully execute a pipeline with a source and a sink until the source is completely exhausted
123773
124193
  void Execute();
124194
+ //! Execute a pipeline with a source and a sink until finished, or until max_chunks have been processed
124195
+ //! Returns true if execution is finished, false if Execute should be called again
124196
+ bool Execute(idx_t max_chunks);
124197
+
123774
124198
  //! Push a single input DataChunk into the pipeline.
123775
124199
  //! Returns either OperatorResultType::NEED_MORE_INPUT or OperatorResultType::FINISHED
123776
124200
  //! If OperatorResultType::FINISHED is returned, more input will not change the result anymore
@@ -123939,7 +124363,7 @@ Executor::~Executor() {
123939
124363
  }
123940
124364
 
123941
124365
  Executor &Executor::Get(ClientContext &context) {
123942
- return context.executor;
124366
+ return context.GetExecutor();
123943
124367
  }
123944
124368
 
123945
124369
  void Executor::AddEvent(shared_ptr<Event> event) {
@@ -124168,16 +124592,6 @@ void Executor::VerifyPipelines() {
124168
124592
  #endif
124169
124593
  }
124170
124594
 
124171
- void Executor::WorkOnTasks() {
124172
- auto &scheduler = TaskScheduler::GetScheduler(context);
124173
-
124174
- unique_ptr<Task> task;
124175
- while (scheduler.GetTaskFromProducer(*producer, task)) {
124176
- task->Execute();
124177
- task.reset();
124178
- }
124179
- }
124180
-
124181
124595
  void Executor::Initialize(PhysicalOperator *plan) {
124182
124596
  Reset();
124183
124597
 
@@ -124186,7 +124600,8 @@ void Executor::Initialize(PhysicalOperator *plan) {
124186
124600
  lock_guard<mutex> elock(executor_lock);
124187
124601
  physical_plan = plan;
124188
124602
 
124189
- context.profiler->Initialize(physical_plan);
124603
+ auto &profiler = QueryProfiler::Get(context);
124604
+ profiler.Initialize(physical_plan);
124190
124605
  this->producer = scheduler.CreateProducer();
124191
124606
 
124192
124607
  auto root_pipeline = make_shared<Pipeline>(*this);
@@ -124202,60 +124617,102 @@ void Executor::Initialize(PhysicalOperator *plan) {
124202
124617
 
124203
124618
  ScheduleEvents();
124204
124619
  }
124620
+ }
124205
124621
 
124206
- // now execute tasks from this producer until all pipelines are completed
124207
- while (completed_pipelines < total_pipelines) {
124208
- WorkOnTasks();
124209
- if (!HasError()) {
124210
- // no exceptions: continue
124211
- continue;
124622
+ void Executor::CancelTasks() {
124623
+ task.reset();
124624
+ // we do this by creating weak pointers to all pipelines
124625
+ // then clearing our references to the pipelines
124626
+ // and waiting until all pipelines have been destroyed
124627
+ vector<weak_ptr<Pipeline>> weak_references;
124628
+ {
124629
+ lock_guard<mutex> elock(executor_lock);
124630
+ if (pipelines.empty()) {
124631
+ return;
124212
124632
  }
124213
-
124214
- // an exception has occurred executing one of the pipelines
124215
- // we need to wait until all threads are finished
124216
- // we do this by creating weak pointers to all pipelines
124217
- // then clearing our references to the pipelines
124218
- // and waiting until all pipelines have been destroyed
124219
- vector<weak_ptr<Pipeline>> weak_references;
124220
- {
124221
- lock_guard<mutex> elock(executor_lock);
124222
- weak_references.reserve(pipelines.size());
124223
- for (auto &pipeline : pipelines) {
124633
+ weak_references.reserve(pipelines.size());
124634
+ for (auto &pipeline : pipelines) {
124635
+ weak_references.push_back(weak_ptr<Pipeline>(pipeline));
124636
+ }
124637
+ for (auto &kv : union_pipelines) {
124638
+ for (auto &pipeline : kv.second) {
124224
124639
  weak_references.push_back(weak_ptr<Pipeline>(pipeline));
124225
124640
  }
124226
- for (auto &kv : union_pipelines) {
124227
- for (auto &pipeline : kv.second) {
124228
- weak_references.push_back(weak_ptr<Pipeline>(pipeline));
124229
- }
124641
+ }
124642
+ for (auto &kv : child_pipelines) {
124643
+ for (auto &pipeline : kv.second) {
124644
+ weak_references.push_back(weak_ptr<Pipeline>(pipeline));
124230
124645
  }
124231
- for (auto &kv : child_pipelines) {
124232
- for (auto &pipeline : kv.second) {
124233
- weak_references.push_back(weak_ptr<Pipeline>(pipeline));
124234
- }
124646
+ }
124647
+ pipelines.clear();
124648
+ union_pipelines.clear();
124649
+ child_pipelines.clear();
124650
+ events.clear();
124651
+ }
124652
+ WorkOnTasks();
124653
+ for (auto &weak_ref : weak_references) {
124654
+ while (true) {
124655
+ auto weak = weak_ref.lock();
124656
+ if (!weak) {
124657
+ break;
124235
124658
  }
124236
- pipelines.clear();
124237
- union_pipelines.clear();
124238
- child_pipelines.clear();
124239
- events.clear();
124240
124659
  }
124241
- for (auto &weak_ref : weak_references) {
124242
- while (true) {
124243
- auto weak = weak_ref.lock();
124244
- if (!weak) {
124245
- break;
124246
- }
124660
+ }
124661
+ }
124662
+
124663
+ void Executor::WorkOnTasks() {
124664
+ auto &scheduler = TaskScheduler::GetScheduler(context);
124665
+
124666
+ unique_ptr<Task> task;
124667
+ while (scheduler.GetTaskFromProducer(*producer, task)) {
124668
+ task->Execute(TaskExecutionMode::PROCESS_ALL);
124669
+ task.reset();
124670
+ }
124671
+ }
124672
+
124673
+ PendingExecutionResult Executor::ExecuteTask() {
124674
+ if (execution_result != PendingExecutionResult::RESULT_NOT_READY) {
124675
+ return execution_result;
124676
+ }
124677
+ // check if there are any incomplete pipelines
124678
+ auto &scheduler = TaskScheduler::GetScheduler(context);
124679
+ while (completed_pipelines < total_pipelines) {
124680
+ // there are! if we don't already have a task, fetch one
124681
+ if (!task) {
124682
+ scheduler.GetTaskFromProducer(*producer, task);
124683
+ }
124684
+ if (task) {
124685
+ // if we have a task, partially process it
124686
+ auto result = task->Execute(TaskExecutionMode::PROCESS_PARTIAL);
124687
+ if (result != TaskExecutionResult::TASK_NOT_FINISHED) {
124688
+ // if the task is finished, clean it up
124689
+ task.reset();
124247
124690
  }
124248
124691
  }
124692
+ if (!HasError()) {
124693
+ // we (partially) processed a task and no exceptions were thrown
124694
+ // give back control to the caller
124695
+ return PendingExecutionResult::RESULT_NOT_READY;
124696
+ }
124697
+ execution_result = PendingExecutionResult::EXECUTION_ERROR;
124698
+
124699
+ // an exception has occurred executing one of the pipelines
124700
+ // we need to cancel all tasks associated with this executor
124701
+ CancelTasks();
124249
124702
  ThrowException();
124250
124703
  }
124704
+ D_ASSERT(!task);
124251
124705
 
124252
124706
  lock_guard<mutex> elock(executor_lock);
124253
124707
  pipelines.clear();
124254
124708
  NextExecutor();
124255
124709
  if (!exceptions.empty()) { // LCOV_EXCL_START
124256
124710
  // an exception has occurred executing one of the pipelines
124711
+ execution_result = PendingExecutionResult::EXECUTION_ERROR;
124257
124712
  ThrowExceptionInternal();
124258
124713
  } // LCOV_EXCL_STOP
124714
+ execution_result = PendingExecutionResult::RESULT_READY;
124715
+ return execution_result;
124259
124716
  }
124260
124717
 
124261
124718
  void Executor::Reset() {
@@ -124274,6 +124731,7 @@ void Executor::Reset() {
124274
124731
  union_pipelines.clear();
124275
124732
  child_pipelines.clear();
124276
124733
  child_dependencies.clear();
124734
+ execution_result = PendingExecutionResult::RESULT_NOT_READY;
124277
124735
  }
124278
124736
 
124279
124737
  void Executor::AddChildPipeline(Pipeline *current) {
@@ -124555,10 +125013,11 @@ void Executor::ThrowExceptionInternal() { // LCOV_EXCL_START
124555
125013
 
124556
125014
  void Executor::Flush(ThreadContext &tcontext) {
124557
125015
  lock_guard<mutex> elock(executor_lock);
124558
- context.profiler->Flush(tcontext.profiler);
125016
+ auto &profiler = QueryProfiler::Get(context);
125017
+ profiler.Flush(tcontext.profiler);
124559
125018
  }
124560
125019
 
124561
- bool Executor::GetPipelinesProgress(int &current_progress) { // LCOV_EXCL_START
125020
+ bool Executor::GetPipelinesProgress(double &current_progress) { // LCOV_EXCL_START
124562
125021
  lock_guard<mutex> elock(executor_lock);
124563
125022
 
124564
125023
  if (!pipelines.empty()) {
@@ -124604,9 +125063,9 @@ ExecutorTask::ExecutorTask(ClientContext &context) : ExecutorTask(Executor::Get(
124604
125063
  ExecutorTask::~ExecutorTask() {
124605
125064
  }
124606
125065
 
124607
- void ExecutorTask::Execute() {
125066
+ TaskExecutionResult ExecutorTask::Execute(TaskExecutionMode mode) {
124608
125067
  try {
124609
- ExecuteTask();
125068
+ return ExecuteTask(mode);
124610
125069
  } catch (Exception &ex) {
124611
125070
  executor.PushError(ex.type, ex.what());
124612
125071
  } catch (std::exception &ex) {
@@ -124614,6 +125073,7 @@ void ExecutorTask::Execute() {
124614
125073
  } catch (...) { // LCOV_EXCL_START
124615
125074
  executor.PushError(ExceptionType::UNKNOWN_TYPE, "Unknown exception in Finalize!");
124616
125075
  } // LCOV_EXCL_STOP
125076
+ return TaskExecutionResult::TASK_ERROR;
124617
125077
  }
124618
125078
 
124619
125079
  } // namespace duckdb
@@ -124641,6 +125101,8 @@ void ExecutorTask::Execute() {
124641
125101
  namespace duckdb {
124642
125102
 
124643
125103
  class PipelineTask : public ExecutorTask {
125104
+ static constexpr const idx_t PARTIAL_CHUNK_COUNT = 50;
125105
+
124644
125106
  public:
124645
125107
  explicit PipelineTask(Pipeline &pipeline_p, shared_ptr<Event> event_p)
124646
125108
  : ExecutorTask(pipeline_p.executor), pipeline(pipeline_p), event(move(event_p)) {
@@ -124648,12 +125110,24 @@ public:
124648
125110
 
124649
125111
  Pipeline &pipeline;
124650
125112
  shared_ptr<Event> event;
125113
+ unique_ptr<PipelineExecutor> pipeline_executor;
124651
125114
 
124652
125115
  public:
124653
- void ExecuteTask() override {
124654
- PipelineExecutor executor(pipeline.GetClientContext(), pipeline);
124655
- executor.Execute();
125116
+ TaskExecutionResult ExecuteTask(TaskExecutionMode mode) override {
125117
+ if (!pipeline_executor) {
125118
+ pipeline_executor = make_unique<PipelineExecutor>(pipeline.GetClientContext(), pipeline);
125119
+ }
125120
+ if (mode == TaskExecutionMode::PROCESS_PARTIAL) {
125121
+ bool finished = pipeline_executor->Execute(PARTIAL_CHUNK_COUNT);
125122
+ if (!finished) {
125123
+ return TaskExecutionResult::TASK_NOT_FINISHED;
125124
+ }
125125
+ } else {
125126
+ pipeline_executor->Execute();
125127
+ }
124656
125128
  event->FinishTask();
125129
+ pipeline_executor.reset();
125130
+ return TaskExecutionResult::TASK_FINISHED;
124657
125131
  }
124658
125132
  };
124659
125133
 
@@ -124665,7 +125139,7 @@ ClientContext &Pipeline::GetClientContext() {
124665
125139
  }
124666
125140
 
124667
125141
  // LCOV_EXCL_START
124668
- bool Pipeline::GetProgressInternal(ClientContext &context, PhysicalOperator *op, int &current_percentage) {
125142
+ bool Pipeline::GetProgressInternal(ClientContext &context, PhysicalOperator *op, double &current_percentage) {
124669
125143
  current_percentage = -1;
124670
125144
  switch (op->type) {
124671
125145
  case PhysicalOperatorType::TABLE_SCAN: {
@@ -124684,7 +125158,7 @@ bool Pipeline::GetProgressInternal(ClientContext &context, PhysicalOperator *op,
124684
125158
  }
124685
125159
  // LCOV_EXCL_STOP
124686
125160
 
124687
- bool Pipeline::GetProgress(int &current_percentage) {
125161
+ bool Pipeline::GetProgress(double &current_percentage) {
124688
125162
  auto &client = executor.context;
124689
125163
  return GetProgressInternal(client, source, current_percentage);
124690
125164
  }
@@ -124885,16 +125359,18 @@ PipelineExecutor::PipelineExecutor(ClientContext &context_p, Pipeline &pipeline_
124885
125359
  InitializeChunk(final_chunk);
124886
125360
  }
124887
125361
 
124888
- void PipelineExecutor::Execute() {
125362
+ bool PipelineExecutor::Execute(idx_t max_chunks) {
124889
125363
  D_ASSERT(pipeline.sink);
125364
+ bool exhausted_source = false;
124890
125365
  auto &source_chunk = pipeline.operators.empty() ? final_chunk : *intermediate_chunks[0];
124891
- while (true) {
125366
+ for (idx_t i = 0; i < max_chunks; i++) {
124892
125367
  if (finished_processing) {
124893
125368
  break;
124894
125369
  }
124895
125370
  source_chunk.Reset();
124896
125371
  FetchFromSource(source_chunk);
124897
125372
  if (source_chunk.size() == 0) {
125373
+ exhausted_source = true;
124898
125374
  break;
124899
125375
  }
124900
125376
  auto result = ExecutePushInternal(source_chunk);
@@ -124903,7 +125379,15 @@ void PipelineExecutor::Execute() {
124903
125379
  break;
124904
125380
  }
124905
125381
  }
125382
+ if (!exhausted_source && !finished_processing) {
125383
+ return false;
125384
+ }
124906
125385
  PushFinalize();
125386
+ return true;
125387
+ }
125388
+
125389
+ void PipelineExecutor::Execute() {
125390
+ Execute(NumericLimits<idx_t>::Maximum());
124907
125391
  }
124908
125392
 
124909
125393
  OperatorResultType PipelineExecutor::ExecutePush(DataChunk &input) { // LCOV_EXCL_START
@@ -129434,7 +129918,7 @@ void TaskScheduler::ExecuteForever(atomic<bool> *marker) {
129434
129918
  // wait for a signal with a timeout; the timeout allows us to periodically check
129435
129919
  queue->semaphore.wait(TASK_TIMEOUT_USECS);
129436
129920
  if (queue->q.try_dequeue(task)) {
129437
- task->Execute();
129921
+ task->Execute(TaskExecutionMode::PROCESS_ALL);
129438
129922
  task.reset();
129439
129923
  }
129440
129924
  }
@@ -129507,7 +129991,7 @@ void TaskScheduler::SetThreadsInternal(int32_t n) {
129507
129991
 
129508
129992
  namespace duckdb {
129509
129993
 
129510
- ThreadContext::ThreadContext(ClientContext &context) : profiler(context.profiler->IsEnabled()) {
129994
+ ThreadContext::ThreadContext(ClientContext &context) : profiler(QueryProfiler::Get(context).IsEnabled()) {
129511
129995
  }
129512
129996
 
129513
129997
  } // namespace duckdb
@@ -154511,13 +154995,15 @@ Planner::Planner(ClientContext &context) : binder(Binder::CreateBinder(context))
154511
154995
  }
154512
154996
 
154513
154997
  void Planner::CreatePlan(SQLStatement &statement) {
154998
+ auto &profiler = QueryProfiler::Get(context);
154999
+
154514
155000
  vector<BoundParameterExpression *> bound_parameters;
154515
155001
 
154516
155002
  // first bind the tables and columns to the catalog
154517
- context.profiler->StartPhase("binder");
155003
+ profiler.StartPhase("binder");
154518
155004
  binder->parameters = &bound_parameters;
154519
155005
  auto bound_statement = binder->Bind(statement);
154520
- context.profiler->EndPhase();
155006
+ profiler.EndPhase();
154521
155007
 
154522
155008
  this->read_only = binder->read_only;
154523
155009
  this->requires_valid_transaction = binder->requires_valid_transaction;