duckdb 0.3.2-dev633.0 → 0.3.2-dev656.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 +795 -493
  3. package/src/duckdb.hpp +5863 -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
24094
+ supported = true;
24109
24095
  }
24110
24096
 
24111
- ProgressBar::~ProgressBar() {
24112
- Stop();
24113
- }
24114
-
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
 
@@ -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
- }
30596
-
30597
- DUCKDB_API void DetailedEnable() {
30598
- detailed_enabled = true;
30599
- }
30527
+ DUCKDB_API bool IsEnabled() const;
30528
+ DUCKDB_API bool IsDetailedEnabled() const;
30529
+ DUCKDB_API ProfilerPrintFormat GetPrintFormat() const;
30530
+ DUCKDB_API string GetSaveLocation() const;
30600
30531
 
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;
@@ -41627,12 +41544,15 @@ static bool TemplatedBooleanOperation(const Value &left, const Value &right) {
41627
41544
  const auto &left_type = left.type();
41628
41545
  const auto &right_type = right.type();
41629
41546
  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 (...) {
41547
+ Value left_copy = left;
41548
+ Value right_copy = right;
41549
+
41550
+ LogicalType comparison_type = BoundComparisonExpression::BindComparison(left_type, right_type);
41551
+ if (!left_copy.TryCastAs(comparison_type) || !right_copy.TryCastAs(comparison_type)) {
41634
41552
  return false;
41635
41553
  }
41554
+ D_ASSERT(left_copy.type() == right_copy.type());
41555
+ return TemplatedBooleanOperation<OP>(left_copy, right_copy);
41636
41556
  }
41637
41557
  switch (left_type.InternalType()) {
41638
41558
  case PhysicalType::BOOL:
@@ -52680,8 +52600,9 @@ void PhysicalSimpleAggregate::Combine(ExecutionContext &context, GlobalSinkState
52680
52600
  aggregate.function.combine(source_state, dest_state, 1);
52681
52601
  }
52682
52602
 
52603
+ auto &client_profiler = QueryProfiler::Get(context.client);
52683
52604
  context.thread.profiler.Flush(this, &source.child_executor, "child_executor", 0);
52684
- context.client.profiler->Flush(context.thread.profiler);
52605
+ client_profiler.Flush(context.thread.profiler);
52685
52606
  }
52686
52607
 
52687
52608
  SinkFinalizeType PhysicalSimpleAggregate::Finalize(Pipeline &pipeline, Event &event, ClientContext &context,
@@ -54486,7 +54407,8 @@ SinkResultType PhysicalExplainAnalyze::Sink(ExecutionContext &context, GlobalSin
54486
54407
  SinkFinalizeType PhysicalExplainAnalyze::Finalize(Pipeline &pipeline, Event &event, ClientContext &context,
54487
54408
  GlobalSinkState &gstate_p) const {
54488
54409
  auto &gstate = (ExplainAnalyzeStateGlobalState &)gstate_p;
54489
- gstate.analyzed_plan = context.profiler->ToString();
54410
+ auto &profiler = QueryProfiler::Get(context);
54411
+ gstate.analyzed_plan = profiler.ToString();
54490
54412
  return SinkFinalizeType::READY;
54491
54413
  }
54492
54414
 
@@ -57267,8 +57189,9 @@ SinkResultType PhysicalHashJoin::Sink(ExecutionContext &context, GlobalSinkState
57267
57189
 
57268
57190
  void PhysicalHashJoin::Combine(ExecutionContext &context, GlobalSinkState &gstate, LocalSinkState &lstate) const {
57269
57191
  auto &state = (HashJoinLocalState &)lstate;
57192
+ auto &client_profiler = QueryProfiler::Get(context.client);
57270
57193
  context.thread.profiler.Flush(this, &state.build_executor, "build_executor", 1);
57271
- context.client.profiler->Flush(context.thread.profiler);
57194
+ client_profiler.Flush(context.thread.profiler);
57272
57195
  }
57273
57196
 
57274
57197
  //===--------------------------------------------------------------------===//
@@ -58032,8 +57955,10 @@ SinkResultType PhysicalNestedLoopJoin::Sink(ExecutionContext &context, GlobalSin
58032
57955
 
58033
57956
  void PhysicalNestedLoopJoin::Combine(ExecutionContext &context, GlobalSinkState &gstate, LocalSinkState &lstate) const {
58034
57957
  auto &state = (NestedLoopJoinLocalState &)lstate;
57958
+ auto &client_profiler = QueryProfiler::Get(context.client);
57959
+
58035
57960
  context.thread.profiler.Flush(this, &state.rhs_executor, "rhs_executor", 1);
58036
- context.client.profiler->Flush(context.thread.profiler);
57961
+ client_profiler.Flush(context.thread.profiler);
58037
57962
  }
58038
57963
 
58039
57964
  SinkFinalizeType PhysicalNestedLoopJoin::Finalize(Pipeline &pipeline, Event &event, ClientContext &context,
@@ -58465,8 +58390,10 @@ SinkResultType PhysicalPiecewiseMergeJoin::Sink(ExecutionContext &context, Globa
58465
58390
  void PhysicalPiecewiseMergeJoin::Combine(ExecutionContext &context, GlobalSinkState &gstate,
58466
58391
  LocalSinkState &lstate) const {
58467
58392
  auto &state = (MergeJoinLocalState &)lstate;
58393
+ auto &client_profiler = QueryProfiler::Get(context.client);
58394
+
58468
58395
  context.thread.profiler.Flush(this, &state.rhs_executor, "rhs_executor", 1);
58469
- context.client.profiler->Flush(context.thread.profiler);
58396
+ client_profiler.Flush(context.thread.profiler);
58470
58397
  }
58471
58398
 
58472
58399
  //===--------------------------------------------------------------------===//
@@ -59051,12 +58978,13 @@ public:
59051
58978
  : ExecutorTask(context), event(move(event_p)), context(context), state(state) {
59052
58979
  }
59053
58980
 
59054
- void ExecuteTask() override {
58981
+ TaskExecutionResult ExecuteTask(TaskExecutionMode mode) override {
59055
58982
  // Initialize merge sorted and iterate until done
59056
58983
  auto &global_sort_state = state.global_sort_state;
59057
58984
  MergeSorter merge_sorter(global_sort_state, BufferManager::GetBufferManager(context));
59058
58985
  merge_sorter.PerformInMergeRound();
59059
58986
  event->FinishTask();
58987
+ return TaskExecutionResult::TASK_FINISHED;
59060
58988
  }
59061
58989
 
59062
58990
  private:
@@ -62392,8 +62320,9 @@ unique_ptr<LocalSinkState> PhysicalInsert::GetLocalSinkState(ExecutionContext &c
62392
62320
 
62393
62321
  void PhysicalInsert::Combine(ExecutionContext &context, GlobalSinkState &gstate, LocalSinkState &lstate) const {
62394
62322
  auto &state = (InsertLocalState &)lstate;
62323
+ auto &client_profiler = QueryProfiler::Get(context.client);
62395
62324
  context.thread.profiler.Flush(this, &state.default_executor, "default_executor", 1);
62396
- context.client.profiler->Flush(context.thread.profiler);
62325
+ client_profiler.Flush(context.thread.profiler);
62397
62326
  }
62398
62327
 
62399
62328
  //===--------------------------------------------------------------------===//
@@ -62599,8 +62528,9 @@ unique_ptr<LocalSinkState> PhysicalUpdate::GetLocalSinkState(ExecutionContext &c
62599
62528
 
62600
62529
  void PhysicalUpdate::Combine(ExecutionContext &context, GlobalSinkState &gstate, LocalSinkState &lstate) const {
62601
62530
  auto &state = (UpdateLocalState &)lstate;
62531
+ auto &client_profiler = QueryProfiler::Get(context.client);
62602
62532
  context.thread.profiler.Flush(this, &state.default_executor, "default_executor", 1);
62603
- context.client.profiler->Flush(context.thread.profiler);
62533
+ client_profiler.Flush(context.thread.profiler);
62604
62534
  }
62605
62535
 
62606
62536
  //===--------------------------------------------------------------------===//
@@ -68596,25 +68526,27 @@ private:
68596
68526
  };
68597
68527
 
68598
68528
  unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(unique_ptr<LogicalOperator> op) {
68529
+ auto &profiler = QueryProfiler::Get(context);
68530
+
68599
68531
  // first resolve column references
68600
- context.profiler->StartPhase("column_binding");
68532
+ profiler.StartPhase("column_binding");
68601
68533
  ColumnBindingResolver resolver;
68602
68534
  resolver.VisitOperator(*op);
68603
- context.profiler->EndPhase();
68535
+ profiler.EndPhase();
68604
68536
 
68605
68537
  // now resolve types of all the operators
68606
- context.profiler->StartPhase("resolve_types");
68538
+ profiler.StartPhase("resolve_types");
68607
68539
  op->ResolveOperatorTypes();
68608
- context.profiler->EndPhase();
68540
+ profiler.EndPhase();
68609
68541
 
68610
68542
  // extract dependencies from the logical plan
68611
68543
  DependencyExtractor extractor(dependencies);
68612
68544
  extractor.VisitOperator(*op);
68613
68545
 
68614
68546
  // then create the main physical plan
68615
- context.profiler->StartPhase("create_plan");
68547
+ profiler.StartPhase("create_plan");
68616
68548
  auto plan = CreatePlan(*op);
68617
- context.profiler->EndPhase();
68549
+ profiler.EndPhase();
68618
68550
  return plan;
68619
68551
  }
68620
68552
 
@@ -68976,6 +68908,7 @@ public:
68976
68908
  idx_t radix_p)
68977
68909
  : ExecutorTask(executor), event(move(event_p)), state(state_p), radix(radix_p) {
68978
68910
  }
68911
+
68979
68912
  static void FinalizeHT(RadixHTGlobalState &gstate, idx_t radix) {
68980
68913
  D_ASSERT(gstate.partition_info.n_partitions <= gstate.finalized_hts.size());
68981
68914
  D_ASSERT(gstate.finalized_hts[radix]);
@@ -68988,9 +68921,10 @@ public:
68988
68921
  gstate.finalized_hts[radix]->Finalize();
68989
68922
  }
68990
68923
 
68991
- void ExecuteTask() override {
68924
+ TaskExecutionResult ExecuteTask(TaskExecutionMode mode) override {
68992
68925
  FinalizeHT(state, radix);
68993
68926
  event->FinishTask();
68927
+ return TaskExecutionResult::TASK_FINISHED;
68994
68928
  }
68995
68929
 
68996
68930
  private:
@@ -78092,8 +78026,9 @@ struct PragmaFunctions {
78092
78026
  namespace duckdb {
78093
78027
 
78094
78028
  static void PragmaEnableProfilingStatement(ClientContext &context, const FunctionParameters &parameters) {
78095
- context.profiler->automatic_print_format = ProfilerPrintFormat::QUERY_TREE;
78096
- context.profiler->Enable();
78029
+ auto &config = ClientConfig::GetConfig(context);
78030
+ config.profiler_print_format = ProfilerPrintFormat::QUERY_TREE;
78031
+ config.enable_profiler = true;
78097
78032
  }
78098
78033
 
78099
78034
  void RegisterEnableProfiling(BuiltinFunctions &set) {
@@ -78105,8 +78040,9 @@ void RegisterEnableProfiling(BuiltinFunctions &set) {
78105
78040
  }
78106
78041
 
78107
78042
  static void PragmaDisableProfiling(ClientContext &context, const FunctionParameters &parameters) {
78108
- context.profiler->Disable();
78109
- context.profiler->automatic_print_format = ProfilerPrintFormat::NONE;
78043
+ auto &config = ClientConfig::GetConfig(context);
78044
+ config.enable_profiler = false;
78045
+ config.profiler_print_format = ProfilerPrintFormat::NONE;
78110
78046
  }
78111
78047
 
78112
78048
  static void PragmaEnableProgressBar(ClientContext &context, const FunctionParameters &parameters) {
@@ -91738,8 +91674,7 @@ unique_ptr<FunctionData> BindSystemFunction(ClientContext &context, ScalarFuncti
91738
91674
 
91739
91675
  static void CurrentQueryFunction(DataChunk &input, ExpressionState &state, Vector &result) {
91740
91676
  auto &info = SystemBindData::GetFrom(state);
91741
-
91742
- Value val(info.context.query);
91677
+ Value val(info.context.GetCurrentQuery());
91743
91678
  result.Reference(val);
91744
91679
  }
91745
91680
 
@@ -91981,6 +91916,21 @@ void ScalarFunction::NopFunction(DataChunk &input, ExpressionState &state, Vecto
91981
91916
 
91982
91917
 
91983
91918
 
91919
+ //===----------------------------------------------------------------------===//
91920
+ // DuckDB
91921
+ //
91922
+ // duckdb/common/thread.hpp
91923
+ //
91924
+ //
91925
+ //===----------------------------------------------------------------------===//
91926
+
91927
+
91928
+
91929
+ #include <thread>
91930
+
91931
+ namespace duckdb {
91932
+ using std::thread;
91933
+ }
91984
91934
 
91985
91935
  #include <map>
91986
91936
  #include <condition_variable>
@@ -92126,7 +92076,7 @@ private:
92126
92076
  //! Gets Arrow Table's Cardinality
92127
92077
  static unique_ptr<NodeStatistics> ArrowScanCardinality(ClientContext &context, const FunctionData *bind_data);
92128
92078
  //! Gets the progress on the table scan, used for Progress Bars
92129
- static int ArrowProgress(ClientContext &context, const FunctionData *bind_data_p);
92079
+ static double ArrowProgress(ClientContext &context, const FunctionData *bind_data_p);
92130
92080
  };
92131
92081
 
92132
92082
  } // namespace duckdb
@@ -93225,12 +93175,12 @@ unique_ptr<NodeStatistics> ArrowTableFunction::ArrowScanCardinality(ClientContex
93225
93175
  return make_unique<NodeStatistics>(bind_data.number_of_rows, bind_data.number_of_rows);
93226
93176
  }
93227
93177
 
93228
- int ArrowTableFunction::ArrowProgress(ClientContext &context, const FunctionData *bind_data_p) {
93178
+ double ArrowTableFunction::ArrowProgress(ClientContext &context, const FunctionData *bind_data_p) {
93229
93179
  auto &bind_data = (const ArrowScanFunctionData &)*bind_data_p;
93230
93180
  if (bind_data.number_of_rows == 0) {
93231
93181
  return 100;
93232
93182
  }
93233
- auto percentage = bind_data.lines_read * 100 / bind_data.number_of_rows;
93183
+ auto percentage = bind_data.lines_read * 100.0 / bind_data.number_of_rows;
93234
93184
  return percentage;
93235
93185
  }
93236
93186
 
@@ -94915,12 +94865,12 @@ static void ReadCSVAddNamedParameters(TableFunction &table_function) {
94915
94865
  table_function.named_parameters["skip"] = LogicalType::BIGINT;
94916
94866
  }
94917
94867
 
94918
- int CSVReaderProgress(ClientContext &context, const FunctionData *bind_data_p) {
94868
+ double CSVReaderProgress(ClientContext &context, const FunctionData *bind_data_p) {
94919
94869
  auto &bind_data = (ReadCSVData &)*bind_data_p;
94920
94870
  if (bind_data.file_size == 0) {
94921
94871
  return 100;
94922
94872
  }
94923
- auto percentage = bind_data.bytes_read * 100 / bind_data.file_size;
94873
+ auto percentage = (bind_data.bytes_read * 100.0) / bind_data.file_size;
94924
94874
  return percentage;
94925
94875
  }
94926
94876
 
@@ -98134,14 +98084,14 @@ bool TableScanParallelStateNext(ClientContext &context, const FunctionData *bind
98134
98084
  state.column_ids);
98135
98085
  }
98136
98086
 
98137
- int TableScanProgress(ClientContext &context, const FunctionData *bind_data_p) {
98087
+ double TableScanProgress(ClientContext &context, const FunctionData *bind_data_p) {
98138
98088
  auto &bind_data = (TableScanBindData &)*bind_data_p;
98139
98089
  idx_t total_rows = bind_data.table->storage->GetTotalRows();
98140
98090
  if (total_rows == 0 || total_rows < STANDARD_VECTOR_SIZE) {
98141
98091
  //! Table is either empty or smaller than a vector size, so it is finished
98142
98092
  return 100;
98143
98093
  }
98144
- auto percentage = (bind_data.chunk_count * STANDARD_VECTOR_SIZE * 100) / total_rows;
98094
+ auto percentage = double(bind_data.chunk_count * STANDARD_VECTOR_SIZE * 100.0) / total_rows;
98145
98095
  if (percentage > 100) {
98146
98096
  //! In case the last chunk has less elements than STANDARD_VECTOR_SIZE, if our percentage is over 100
98147
98097
  //! It means we finished this table.
@@ -100877,28 +100827,27 @@ private:
100877
100827
 
100878
100828
  namespace duckdb {
100879
100829
 
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;
100830
+ struct ActiveQueryContext {
100831
+ //! The query that is currently being executed
100832
+ string query;
100833
+ //! The currently open result
100834
+ BaseQueryResult *open_result = nullptr;
100835
+ //! Prepared statement data
100836
+ shared_ptr<PreparedStatementData> prepared;
100837
+ //! The query executor
100838
+ unique_ptr<Executor> executor;
100839
+ //! The progress bar
100840
+ unique_ptr<ProgressBar> progress_bar;
100890
100841
  };
100891
100842
 
100892
100843
  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),
100844
+ : profiler(make_unique<QueryProfiler>(*this)), query_profiler_history(make_unique<QueryProfilerHistory>()),
100845
+ db(move(database)), transaction(db->GetTransactionManager(), *this), interrupted(false),
100895
100846
  temporary_objects(make_unique<SchemaCatalogEntry>(&db->GetCatalog(), TEMP_SCHEMA, true)),
100896
100847
  catalog_search_path(make_unique<CatalogSearchPath>(*this)),
100897
- file_opener(make_unique<ClientContextFileOpener>(*this)), open_result(nullptr) {
100848
+ file_opener(make_unique<ClientContextFileOpener>(*this)) {
100898
100849
  std::random_device rd;
100899
100850
  random_engine.seed(rd());
100900
-
100901
- progress_bar = make_unique<ProgressBar>(&executor, config.wait_time);
100902
100851
  }
100903
100852
 
100904
100853
  ClientContext::~ClientContext() {
@@ -100925,87 +100874,162 @@ void ClientContext::Destroy() {
100925
100874
  CleanupInternal(*lock);
100926
100875
  }
100927
100876
 
100928
- void ClientContext::Cleanup() {
100929
- auto lock = LockContext();
100930
- CleanupInternal(*lock);
100877
+ unique_ptr<DataChunk> ClientContext::Fetch(ClientContextLock &lock, StreamQueryResult &result) {
100878
+ D_ASSERT(IsActiveResult(lock, &result));
100879
+ D_ASSERT(active_query->executor);
100880
+ return FetchInternal(lock, *active_query->executor, result);
100931
100881
  }
100932
100882
 
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
- }
100883
+ unique_ptr<DataChunk> ClientContext::FetchInternal(ClientContextLock &lock, Executor &executor,
100884
+ BaseQueryResult &result) {
100885
+ bool invalidate_query = true;
100938
100886
  try {
100939
100887
  // fetch the chunk and return it
100940
- auto chunk = FetchInternal(*lock);
100888
+ auto chunk = executor.FetchChunk();
100889
+ if (!chunk || chunk->size() == 0) {
100890
+ CleanupInternal(lock, &result);
100891
+ }
100941
100892
  return chunk;
100893
+ } catch (StandardException &ex) {
100894
+ // standard exceptions do not invalidate the current transaction
100895
+ result.error = ex.what();
100896
+ invalidate_query = false;
100942
100897
  } catch (std::exception &ex) {
100943
- open_result->error = ex.what();
100898
+ result.error = ex.what();
100944
100899
  } catch (...) { // LCOV_EXCL_START
100945
- open_result->error = "Unhandled exception in Fetch";
100900
+ result.error = "Unhandled exception in FetchInternal";
100946
100901
  } // LCOV_EXCL_STOP
100947
- open_result->success = false;
100948
- CleanupInternal(*lock);
100902
+ result.success = false;
100903
+ CleanupInternal(lock, &result, invalidate_query);
100949
100904
  return nullptr;
100950
100905
  }
100951
100906
 
100952
- string ClientContext::FinalizeQuery(ClientContextLock &lock, bool success) {
100907
+ void ClientContext::BeginTransactionInternal(ClientContextLock &lock, bool requires_valid_transaction) {
100908
+ // check if we are on AutoCommit. In this case we should start a transaction
100909
+ D_ASSERT(!active_query);
100910
+ if (requires_valid_transaction && transaction.HasActiveTransaction() &&
100911
+ transaction.ActiveTransaction().IsInvalidated()) {
100912
+ throw Exception("Failed: transaction has been invalidated!");
100913
+ }
100914
+ active_query = make_unique<ActiveQueryContext>();
100915
+ if (transaction.IsAutoCommit()) {
100916
+ transaction.BeginTransaction();
100917
+ }
100918
+ }
100919
+
100920
+ void ClientContext::BeginQueryInternal(ClientContextLock &lock, const string &query) {
100921
+ BeginTransactionInternal(lock, false);
100922
+ LogQueryInternal(lock, query);
100923
+ active_query->query = query;
100924
+ query_progress = -1;
100925
+ ActiveTransaction().active_query = db->GetTransactionManager().GetQueryNumber();
100926
+ }
100927
+
100928
+ string ClientContext::EndQueryInternal(ClientContextLock &lock, bool success, bool invalidate_transaction) {
100953
100929
  profiler->EndQuery();
100954
- executor.Reset();
100955
100930
 
100931
+ D_ASSERT(active_query.get());
100956
100932
  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 {
100933
+ try {
100934
+ if (transaction.HasActiveTransaction()) {
100935
+ // Move the query profiler into the history
100936
+ auto &prev_profilers = query_profiler_history->GetPrevProfilers();
100937
+ prev_profilers.emplace_back(transaction.ActiveTransaction().active_query, move(profiler));
100938
+ // Reinitialize the query profiler
100939
+ profiler = make_unique<QueryProfiler>(*this);
100940
+ // Propagate settings of the saved query into the new profiler.
100941
+ profiler->Propagate(*prev_profilers.back().second);
100942
+ if (prev_profilers.size() >= query_profiler_history->GetPrevProfilersSize()) {
100943
+ prev_profilers.pop_front();
100944
+ }
100945
+
100946
+ ActiveTransaction().active_query = MAXIMUM_QUERY_ID;
100970
100947
  if (transaction.IsAutoCommit()) {
100971
100948
  if (success) {
100972
- // query was successful: commit
100973
100949
  transaction.Commit();
100974
100950
  } else {
100975
- // query was unsuccessful: rollback
100976
100951
  transaction.Rollback();
100977
100952
  }
100953
+ } else if (invalidate_transaction) {
100954
+ D_ASSERT(!success);
100955
+ ActiveTransaction().Invalidate();
100978
100956
  }
100979
- } catch (std::exception &ex) {
100980
- error = ex.what();
100981
- } catch (...) { // LCOV_EXCL_START
100982
- error = "Unhandled exception!";
100983
- } // LCOV_EXCL_STOP
100984
- }
100957
+ }
100958
+ } catch (std::exception &ex) {
100959
+ error = ex.what();
100960
+ } catch (...) { // LCOV_EXCL_START
100961
+ error = "Unhandled exception!";
100962
+ } // LCOV_EXCL_STOP
100963
+ active_query.reset();
100964
+ query_progress = -1;
100985
100965
  return error;
100986
100966
  }
100987
100967
 
100988
- void ClientContext::CleanupInternal(ClientContextLock &lock) {
100989
- if (!open_result) {
100990
- // no result currently open
100968
+ void ClientContext::CleanupInternal(ClientContextLock &lock, BaseQueryResult *result, bool invalidate_transaction) {
100969
+ if (!active_query) {
100970
+ // no query currently active
100991
100971
  return;
100992
100972
  }
100973
+ if (active_query->executor) {
100974
+ active_query->executor->CancelTasks();
100975
+ }
100976
+ active_query->progress_bar.reset();
100993
100977
 
100994
- auto error = FinalizeQuery(lock, open_result->success);
100995
- if (open_result->success) {
100978
+ auto error = EndQueryInternal(lock, result ? result->success : false, invalidate_transaction);
100979
+ if (result && result->success) {
100996
100980
  // if an error occurred while committing report it in the result
100997
- open_result->error = error;
100998
- open_result->success = error.empty();
100981
+ result->error = error;
100982
+ result->success = error.empty();
100999
100983
  }
100984
+ D_ASSERT(!active_query);
100985
+ }
101000
100986
 
101001
- open_result->is_open = false;
101002
- open_result = nullptr;
100987
+ Executor &ClientContext::GetExecutor() {
100988
+ D_ASSERT(active_query);
100989
+ D_ASSERT(active_query->executor);
100990
+ return *active_query->executor;
100991
+ }
101003
100992
 
101004
- this->query = string();
100993
+ const string &ClientContext::GetCurrentQuery() {
100994
+ D_ASSERT(active_query);
100995
+ return active_query->query;
101005
100996
  }
101006
100997
 
101007
- unique_ptr<DataChunk> ClientContext::FetchInternal(ClientContextLock &) {
101008
- return executor.FetchChunk();
100998
+ unique_ptr<QueryResult> ClientContext::FetchResultInternal(ClientContextLock &lock, PendingQueryResult &pending,
100999
+ bool allow_stream_result) {
101000
+ D_ASSERT(active_query);
101001
+ D_ASSERT(active_query->open_result == &pending);
101002
+ D_ASSERT(active_query->prepared);
101003
+ auto &prepared = *active_query->prepared;
101004
+ bool create_stream_result = prepared.allow_stream_result && allow_stream_result;
101005
+ if (create_stream_result) {
101006
+ active_query->progress_bar.reset();
101007
+ query_progress = -1;
101008
+
101009
+ // successfully compiled SELECT clause and it is the last statement
101010
+ // return a StreamQueryResult so the client can call Fetch() on it and stream the result
101011
+ auto stream_result =
101012
+ make_unique<StreamQueryResult>(pending.statement_type, shared_from_this(), pending.types, pending.names);
101013
+ active_query->open_result = stream_result.get();
101014
+ return move(stream_result);
101015
+ }
101016
+ // create a materialized result by continuously fetching
101017
+ auto result = make_unique<MaterializedQueryResult>(pending.statement_type, pending.types, pending.names);
101018
+ while (true) {
101019
+ auto chunk = FetchInternal(lock, GetExecutor(), *result);
101020
+ if (!chunk || chunk->size() == 0) {
101021
+ break;
101022
+ }
101023
+ #ifdef DEBUG
101024
+ for (idx_t i = 0; i < chunk->ColumnCount(); i++) {
101025
+ if (pending.types[i].id() == LogicalTypeId::VARCHAR) {
101026
+ chunk->data[i].UTFVerify(chunk->size());
101027
+ }
101028
+ }
101029
+ #endif
101030
+ result->collection.Append(*chunk);
101031
+ }
101032
+ return move(result);
101009
101033
  }
101010
101034
 
101011
101035
  shared_ptr<PreparedStatementData> ClientContext::CreatePreparedStatement(ClientContextLock &lock, const string &query,
@@ -101013,11 +101037,12 @@ shared_ptr<PreparedStatementData> ClientContext::CreatePreparedStatement(ClientC
101013
101037
  StatementType statement_type = statement->type;
101014
101038
  auto result = make_shared<PreparedStatementData>(statement_type);
101015
101039
 
101016
- profiler->StartPhase("planner");
101040
+ auto &profiler = QueryProfiler::Get(*this);
101041
+ profiler.StartPhase("planner");
101017
101042
  Planner planner(*this);
101018
101043
  planner.CreatePlan(move(statement));
101019
101044
  D_ASSERT(planner.plan);
101020
- profiler->EndPhase();
101045
+ profiler.EndPhase();
101021
101046
 
101022
101047
  auto plan = move(planner.plan);
101023
101048
  #ifdef DEBUG
@@ -101033,22 +101058,22 @@ shared_ptr<PreparedStatementData> ClientContext::CreatePreparedStatement(ClientC
101033
101058
  result->catalog_version = Transaction::GetTransaction(*this).catalog_version;
101034
101059
 
101035
101060
  if (config.enable_optimizer) {
101036
- profiler->StartPhase("optimizer");
101061
+ profiler.StartPhase("optimizer");
101037
101062
  Optimizer optimizer(*planner.binder, *this);
101038
101063
  plan = optimizer.Optimize(move(plan));
101039
101064
  D_ASSERT(plan);
101040
- profiler->EndPhase();
101065
+ profiler.EndPhase();
101041
101066
 
101042
101067
  #ifdef DEBUG
101043
101068
  plan->Verify();
101044
101069
  #endif
101045
101070
  }
101046
101071
 
101047
- profiler->StartPhase("physical_planner");
101072
+ profiler.StartPhase("physical_planner");
101048
101073
  // now convert logical query plan into a physical query plan
101049
101074
  PhysicalPlanGenerator physical_planner(*this);
101050
101075
  auto physical_plan = physical_planner.CreatePlan(move(plan));
101051
- profiler->EndPhase();
101076
+ profiler.EndPhase();
101052
101077
 
101053
101078
  #ifdef DEBUG
101054
101079
  D_ASSERT(!physical_plan->ToString().empty());
@@ -101057,14 +101082,14 @@ shared_ptr<PreparedStatementData> ClientContext::CreatePreparedStatement(ClientC
101057
101082
  return result;
101058
101083
  }
101059
101084
 
101060
- int ClientContext::GetProgress() {
101061
- D_ASSERT(progress_bar);
101062
- return progress_bar->GetCurrentPercentage();
101085
+ double ClientContext::GetProgress() {
101086
+ return query_progress.load();
101063
101087
  }
101064
101088
 
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) {
101089
+ unique_ptr<PendingQueryResult> ClientContext::PendingPreparedStatement(ClientContextLock &lock,
101090
+ shared_ptr<PreparedStatementData> statement_p,
101091
+ vector<Value> bound_values) {
101092
+ D_ASSERT(active_query);
101068
101093
  auto &statement = *statement_p;
101069
101094
  if (ActiveTransaction().IsInvalidated() && statement.requires_valid_transaction) {
101070
101095
  throw Exception("Current transaction is aborted (please ROLLBACK)");
@@ -101078,47 +101103,42 @@ unique_ptr<QueryResult> ClientContext::ExecutePreparedStatement(ClientContextLoc
101078
101103
  // bind the bound values before execution
101079
101104
  statement.Bind(move(bound_values));
101080
101105
 
101081
- bool create_stream_result = statement.allow_stream_result && allow_stream_result;
101106
+ active_query->executor = make_unique<Executor>(*this);
101107
+ auto &executor = *active_query->executor;
101082
101108
  if (config.enable_progress_bar) {
101083
- progress_bar->Initialize(config.wait_time);
101084
- progress_bar->Start();
101109
+ active_query->progress_bar = make_unique<ProgressBar>(executor, config.wait_time);
101110
+ active_query->progress_bar->Start();
101111
+ query_progress = 0;
101085
101112
  }
101086
- // store the physical plan in the context for calls to Fetch()
101087
101113
  executor.Initialize(statement.plan.get());
101088
-
101089
101114
  auto types = executor.GetTypes();
101090
-
101091
101115
  D_ASSERT(types == statement.types);
101116
+ D_ASSERT(!active_query->open_result);
101092
101117
 
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
- }
101118
+ auto pending_result = make_unique<PendingQueryResult>(shared_from_this(), *statement_p, move(types));
101119
+ active_query->prepared = move(statement_p);
101120
+ active_query->open_result = pending_result.get();
101121
+ return pending_result;
101122
+ }
101123
+
101124
+ PendingExecutionResult ClientContext::ExecuteTaskInternal(ClientContextLock &lock, PendingQueryResult &result) {
101125
+ D_ASSERT(active_query);
101126
+ D_ASSERT(active_query->open_result == &result);
101127
+ try {
101128
+ auto result = active_query->executor->ExecuteTask();
101129
+ if (active_query->progress_bar) {
101130
+ active_query->progress_bar->Update(result == PendingExecutionResult::RESULT_READY);
101131
+ query_progress = active_query->progress_bar->GetCurrentPercentage();
101114
101132
  }
101115
- #endif
101116
- result->collection.Append(*chunk);
101117
- }
101118
- if (config.enable_progress_bar) {
101119
- progress_bar->Stop();
101120
- }
101121
- return move(result);
101133
+ return result;
101134
+ } catch (std::exception &ex) {
101135
+ result.error = ex.what();
101136
+ } catch (...) { // LCOV_EXCL_START
101137
+ result.error = "Unhandled exception in ExecuteTaskInternal";
101138
+ } // LCOV_EXCL_STOP
101139
+ EndQueryInternal(lock, false, true);
101140
+ result.success = false;
101141
+ return PendingExecutionResult::EXECUTION_ERROR;
101122
101142
  }
101123
101143
 
101124
101144
  void ClientContext::InitialCleanup(ClientContextLock &lock) {
@@ -101221,27 +101241,58 @@ unique_ptr<PreparedStatement> ClientContext::Prepare(const string &query) {
101221
101241
  }
101222
101242
  }
101223
101243
 
101244
+ unique_ptr<PendingQueryResult> ClientContext::PendingQueryPreparedInternal(ClientContextLock &lock, const string &query,
101245
+ shared_ptr<PreparedStatementData> &prepared,
101246
+ vector<Value> &values) {
101247
+ try {
101248
+ InitialCleanup(lock);
101249
+ } catch (std::exception &ex) {
101250
+ return make_unique<PendingQueryResult>(ex.what());
101251
+ }
101252
+ return PendingStatementOrPreparedStatementInternal(lock, query, nullptr, prepared, &values);
101253
+ }
101254
+
101255
+ unique_ptr<PendingQueryResult>
101256
+ ClientContext::PendingQuery(const string &query, shared_ptr<PreparedStatementData> &prepared, vector<Value> &values) {
101257
+ auto lock = LockContext();
101258
+ return PendingQueryPreparedInternal(*lock, query, prepared, values);
101259
+ }
101260
+
101224
101261
  unique_ptr<QueryResult> ClientContext::Execute(const string &query, shared_ptr<PreparedStatementData> &prepared,
101225
101262
  vector<Value> &values, bool allow_stream_result) {
101226
101263
  auto lock = LockContext();
101227
- try {
101228
- InitialCleanup(*lock);
101229
- } catch (std::exception &ex) {
101230
- return make_unique<MaterializedQueryResult>(ex.what());
101264
+ auto pending = PendingQueryPreparedInternal(*lock, query, prepared, values);
101265
+ if (!pending->success) {
101266
+ return make_unique<MaterializedQueryResult>(pending->error);
101231
101267
  }
101232
- LogQueryInternal(*lock, query);
101233
- return RunStatementOrPreparedStatement(*lock, query, nullptr, prepared, &values, allow_stream_result);
101268
+ return pending->ExecuteInternal(*lock, allow_stream_result);
101234
101269
  }
101235
101270
 
101236
- unique_ptr<QueryResult> ClientContext::RunStatementInternal(ClientContextLock &lock, const string &query,
101237
- unique_ptr<SQLStatement> statement,
101238
- bool allow_stream_result) {
101271
+ unique_ptr<PendingQueryResult> ClientContext::PendingStatementInternal(ClientContextLock &lock, const string &query,
101272
+ unique_ptr<SQLStatement> statement) {
101239
101273
  // prepare the query for execution
101240
101274
  auto prepared = CreatePreparedStatement(lock, query, move(statement));
101241
101275
  // by default, no values are bound
101242
101276
  vector<Value> bound_values;
101243
101277
  // execute the prepared statement
101244
- return ExecutePreparedStatement(lock, query, move(prepared), move(bound_values), allow_stream_result);
101278
+ return PendingPreparedStatement(lock, move(prepared), move(bound_values));
101279
+ }
101280
+
101281
+ unique_ptr<QueryResult> ClientContext::RunStatementInternal(ClientContextLock &lock, const string &query,
101282
+ unique_ptr<SQLStatement> statement,
101283
+ bool allow_stream_result, bool verify) {
101284
+ auto pending = PendingQueryInternal(lock, move(statement), verify);
101285
+ if (!pending->success) {
101286
+ return make_unique<MaterializedQueryResult>(move(pending->error));
101287
+ }
101288
+ return ExecutePendingQueryInternal(lock, *pending, allow_stream_result);
101289
+ }
101290
+
101291
+ bool ClientContext::IsActiveResult(ClientContextLock &lock, BaseQueryResult *result) {
101292
+ if (!active_query) {
101293
+ return false;
101294
+ }
101295
+ return active_query->open_result == result;
101245
101296
  }
101246
101297
 
101247
101298
  static bool IsExplainAnalyze(SQLStatement *statement) {
@@ -101255,19 +101306,10 @@ static bool IsExplainAnalyze(SQLStatement *statement) {
101255
101306
  return explain.explain_type == ExplainType::EXPLAIN_ANALYZE;
101256
101307
  }
101257
101308
 
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;
101309
+ unique_ptr<PendingQueryResult> ClientContext::PendingStatementOrPreparedStatementInternal(
101310
+ ClientContextLock &lock, const string &query, unique_ptr<SQLStatement> statement,
101311
+ shared_ptr<PreparedStatementData> &prepared, vector<Value> *values) {
101266
101312
  // 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
101313
  if (statement && config.query_verification_enabled) {
101272
101314
  // query verification is enabled
101273
101315
  // create a copy of the statement, and use the copy
@@ -101277,19 +101319,29 @@ unique_ptr<QueryResult> ClientContext::RunStatementOrPreparedStatement(ClientCon
101277
101319
  // in case this is a select query, we verify the original statement
101278
101320
  string error = VerifyQuery(lock, query, move(statement));
101279
101321
  if (!error.empty()) {
101280
- // query failed: abort now
101281
- FinalizeQuery(lock, false);
101282
101322
  // error in verifying query
101283
- return make_unique<MaterializedQueryResult>(error);
101323
+ return make_unique<PendingQueryResult>(error);
101284
101324
  }
101285
101325
  }
101286
101326
  statement = move(copied_statement);
101287
101327
  }
101328
+ return PendingStatementOrPreparedStatement(lock, query, move(statement), prepared, values);
101329
+ }
101330
+
101331
+ unique_ptr<PendingQueryResult>
101332
+ ClientContext::PendingStatementOrPreparedStatement(ClientContextLock &lock, const string &query,
101333
+ unique_ptr<SQLStatement> statement,
101334
+ shared_ptr<PreparedStatementData> &prepared, vector<Value> *values) {
101335
+ unique_ptr<PendingQueryResult> result;
101336
+
101337
+ BeginQueryInternal(lock, query);
101288
101338
  // start the profiler
101289
- profiler->StartQuery(query, IsExplainAnalyze(statement ? statement.get() : prepared->unbound_statement.get()));
101339
+ auto &profiler = QueryProfiler::Get(*this);
101340
+ profiler.StartQuery(query, IsExplainAnalyze(statement ? statement.get() : prepared->unbound_statement.get()));
101341
+ bool invalidate_query = true;
101290
101342
  try {
101291
101343
  if (statement) {
101292
- result = RunStatementInternal(lock, query, move(statement), allow_stream_result);
101344
+ result = PendingStatementInternal(lock, query, move(statement));
101293
101345
  } else {
101294
101346
  auto &catalog = Catalog::GetCatalog(*this);
101295
101347
  if (prepared->unbound_statement && catalog.GetCatalogVersion() != prepared->catalog_version) {
@@ -101302,68 +101354,22 @@ unique_ptr<QueryResult> ClientContext::RunStatementOrPreparedStatement(ClientCon
101302
101354
  new_prepared->unbound_statement = move(prepared->unbound_statement);
101303
101355
  prepared = move(new_prepared);
101304
101356
  }
101305
- result = ExecutePreparedStatement(lock, query, prepared, *values, allow_stream_result);
101357
+ result = PendingPreparedStatement(lock, prepared, *values);
101306
101358
  }
101307
101359
  } catch (StandardException &ex) {
101308
101360
  // standard exceptions do not invalidate the current transaction
101309
- result = make_unique<MaterializedQueryResult>(ex.what());
101361
+ result = make_unique<PendingQueryResult>(ex.what());
101362
+ invalidate_query = false;
101310
101363
  } catch (std::exception &ex) {
101311
101364
  // other types of exceptions do invalidate the current transaction
101312
- if (transaction.HasActiveTransaction()) {
101313
- ActiveTransaction().Invalidate();
101314
- }
101315
- result = make_unique<MaterializedQueryResult>(ex.what());
101365
+ result = make_unique<PendingQueryResult>(ex.what());
101316
101366
  }
101317
101367
  if (!result->success) {
101318
- // initial failures should always be reported as MaterializedResult
101319
- D_ASSERT(result->type != QueryResultType::STREAM_RESULT);
101320
101368
  // query failed: abort now
101321
- FinalizeQuery(lock, false);
101369
+ EndQueryInternal(lock, false, invalidate_query);
101322
101370
  return result;
101323
101371
  }
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
- }
101372
+ D_ASSERT(active_query->open_result == result.get());
101367
101373
  return result;
101368
101374
  }
101369
101375
 
@@ -101389,34 +101395,96 @@ void ClientContext::LogQueryInternal(ClientContextLock &, const string &query) {
101389
101395
  }
101390
101396
 
101391
101397
  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);
101398
+ auto pending_query = PendingQuery(move(statement));
101399
+ return pending_query->Execute(allow_stream_result);
101399
101400
  }
101400
101401
 
101401
101402
  unique_ptr<QueryResult> ClientContext::Query(const string &query, bool allow_stream_result) {
101402
101403
  auto lock = LockContext();
101403
- LogQueryInternal(*lock, query);
101404
101404
 
101405
+ string error;
101405
101406
  vector<unique_ptr<SQLStatement>> statements;
101407
+ if (!ParseStatements(*lock, query, statements, error)) {
101408
+ return make_unique<MaterializedQueryResult>(move(error));
101409
+ }
101410
+ if (statements.empty()) {
101411
+ // no statements, return empty successful result
101412
+ return make_unique<MaterializedQueryResult>(StatementType::INVALID_STATEMENT);
101413
+ }
101414
+
101415
+ unique_ptr<QueryResult> result;
101416
+ QueryResult *last_result = nullptr;
101417
+ for (idx_t i = 0; i < statements.size(); i++) {
101418
+ auto &statement = statements[i];
101419
+ bool is_last_statement = i + 1 == statements.size();
101420
+ bool stream_result = allow_stream_result && is_last_statement;
101421
+ auto pending_query = PendingQueryInternal(*lock, move(statement));
101422
+ unique_ptr<QueryResult> current_result;
101423
+ if (!pending_query->success) {
101424
+ current_result = make_unique<MaterializedQueryResult>(pending_query->error);
101425
+ } else {
101426
+ current_result = ExecutePendingQueryInternal(*lock, *pending_query, stream_result);
101427
+ }
101428
+ // now append the result to the list of results
101429
+ if (!last_result) {
101430
+ // first result of the query
101431
+ result = move(current_result);
101432
+ last_result = result.get();
101433
+ } else {
101434
+ // later results; attach to the result chain
101435
+ last_result->next = move(current_result);
101436
+ last_result = last_result->next.get();
101437
+ }
101438
+ }
101439
+ return result;
101440
+ }
101441
+
101442
+ bool ClientContext::ParseStatements(ClientContextLock &lock, const string &query,
101443
+ vector<unique_ptr<SQLStatement>> &result, string &error) {
101406
101444
  try {
101407
- InitialCleanup(*lock);
101445
+ InitialCleanup(lock);
101408
101446
  // parse the query and transform it into a set of statements
101409
- statements = ParseStatementsInternal(*lock, query);
101447
+ result = ParseStatementsInternal(lock, query);
101448
+ return true;
101410
101449
  } catch (std::exception &ex) {
101411
- return make_unique<MaterializedQueryResult>(ex.what());
101450
+ error = ex.what();
101451
+ return false;
101412
101452
  }
101453
+ }
101413
101454
 
101414
- if (statements.empty()) {
101415
- // no statements, return empty successful result
101416
- return make_unique<MaterializedQueryResult>(StatementType::INVALID_STATEMENT);
101455
+ unique_ptr<PendingQueryResult> ClientContext::PendingQuery(const string &query) {
101456
+ auto lock = LockContext();
101457
+
101458
+ string error;
101459
+ vector<unique_ptr<SQLStatement>> statements;
101460
+ if (!ParseStatements(*lock, query, statements, error)) {
101461
+ return make_unique<PendingQueryResult>(move(error));
101462
+ }
101463
+ if (statements.size() != 1) {
101464
+ return make_unique<PendingQueryResult>("PendingQuery can only take a single statement");
101465
+ }
101466
+ return PendingQueryInternal(*lock, move(statements[0]));
101467
+ }
101468
+
101469
+ unique_ptr<PendingQueryResult> ClientContext::PendingQuery(unique_ptr<SQLStatement> statement) {
101470
+ auto lock = LockContext();
101471
+ return PendingQueryInternal(*lock, move(statement));
101472
+ }
101473
+
101474
+ unique_ptr<PendingQueryResult> ClientContext::PendingQueryInternal(ClientContextLock &lock,
101475
+ unique_ptr<SQLStatement> statement, bool verify) {
101476
+ auto query = statement->query;
101477
+ shared_ptr<PreparedStatementData> prepared;
101478
+ if (verify) {
101479
+ return PendingStatementOrPreparedStatementInternal(lock, query, move(statement), prepared, nullptr);
101480
+ } else {
101481
+ return PendingStatementOrPreparedStatement(lock, query, move(statement), prepared, nullptr);
101417
101482
  }
101483
+ }
101418
101484
 
101419
- return RunStatements(*lock, query, statements, allow_stream_result);
101485
+ unique_ptr<QueryResult> ClientContext::ExecutePendingQueryInternal(ClientContextLock &lock, PendingQueryResult &query,
101486
+ bool allow_stream_result) {
101487
+ return query.ExecuteInternal(lock, allow_stream_result);
101420
101488
  }
101421
101489
 
101422
101490
  void ClientContext::Interrupt() {
@@ -101425,12 +101493,14 @@ void ClientContext::Interrupt() {
101425
101493
 
101426
101494
  void ClientContext::EnableProfiling() {
101427
101495
  auto lock = LockContext();
101428
- profiler->Enable();
101496
+ auto &config = ClientConfig::GetConfig(*this);
101497
+ config.enable_profiler = true;
101429
101498
  }
101430
101499
 
101431
101500
  void ClientContext::DisableProfiling() {
101432
101501
  auto lock = LockContext();
101433
- profiler->Disable();
101502
+ auto &config = ClientConfig::GetConfig(*this);
101503
+ config.enable_profiler = false;
101434
101504
  }
101435
101505
 
101436
101506
  string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query, unique_ptr<SQLStatement> statement) {
@@ -101492,9 +101562,10 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
101492
101562
  #endif
101493
101563
 
101494
101564
  // disable profiling if it is enabled
101495
- bool profiling_is_enabled = profiler->IsEnabled();
101565
+ auto &config = ClientConfig::GetConfig(*this);
101566
+ bool profiling_is_enabled = config.enable_profiler;
101496
101567
  if (profiling_is_enabled) {
101497
- profiler->Disable();
101568
+ config.enable_profiler = false;
101498
101569
  }
101499
101570
 
101500
101571
  // see below
@@ -101511,7 +101582,7 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
101511
101582
 
101512
101583
  // execute the original statement
101513
101584
  try {
101514
- auto result = RunStatementInternal(lock, query, move(statement), false);
101585
+ auto result = RunStatementInternal(lock, query, move(statement), false, false);
101515
101586
  original_result = unique_ptr_cast<QueryResult, MaterializedQueryResult>(move(result));
101516
101587
  } catch (std::exception &ex) {
101517
101588
  original_result->error = ex.what();
@@ -101524,7 +101595,7 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
101524
101595
  auto explain_q = "EXPLAIN " + query;
101525
101596
  auto explain_stmt = make_unique<ExplainStatement>(move(statement_copy_for_explain));
101526
101597
  try {
101527
- RunStatementInternal(lock, explain_q, move(explain_stmt), false);
101598
+ RunStatementInternal(lock, explain_q, move(explain_stmt), false, false);
101528
101599
  } catch (std::exception &ex) { // LCOV_EXCL_START
101529
101600
  return "EXPLAIN failed but query did not (" + string(ex.what()) + ")";
101530
101601
  } // LCOV_EXCL_STOP
@@ -101532,7 +101603,7 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
101532
101603
 
101533
101604
  // now execute the copied statement
101534
101605
  try {
101535
- auto result = RunStatementInternal(lock, query, move(copied_stmt), false);
101606
+ auto result = RunStatementInternal(lock, query, move(copied_stmt), false, false);
101536
101607
  copied_result = unique_ptr_cast<QueryResult, MaterializedQueryResult>(move(result));
101537
101608
  } catch (std::exception &ex) {
101538
101609
  copied_result->error = ex.what();
@@ -101541,7 +101612,7 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
101541
101612
  }
101542
101613
  // now execute the deserialized statement
101543
101614
  try {
101544
- auto result = RunStatementInternal(lock, query, move(deserialized_stmt), false);
101615
+ auto result = RunStatementInternal(lock, query, move(deserialized_stmt), false, false);
101545
101616
  deserialized_result = unique_ptr_cast<QueryResult, MaterializedQueryResult>(move(result));
101546
101617
  } catch (std::exception &ex) {
101547
101618
  deserialized_result->error = ex.what();
@@ -101551,7 +101622,7 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
101551
101622
  // now execute the unoptimized statement
101552
101623
  config.enable_optimizer = false;
101553
101624
  try {
101554
- auto result = RunStatementInternal(lock, query, move(unoptimized_stmt), false);
101625
+ auto result = RunStatementInternal(lock, query, move(unoptimized_stmt), false, false);
101555
101626
  unoptimized_result = unique_ptr_cast<QueryResult, MaterializedQueryResult>(move(result));
101556
101627
  } catch (std::exception &ex) {
101557
101628
  unoptimized_result->error = ex.what();
@@ -101561,7 +101632,7 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
101561
101632
  config.enable_optimizer = true;
101562
101633
 
101563
101634
  if (profiling_is_enabled) {
101564
- profiler->Enable();
101635
+ config.enable_profiler = true;
101565
101636
  }
101566
101637
 
101567
101638
  // now compare the results
@@ -101615,7 +101686,7 @@ bool ClientContext::UpdateFunctionInfoFromEntry(ScalarFunctionCatalogEntry *exis
101615
101686
  void ClientContext::RegisterFunction(CreateFunctionInfo *info) {
101616
101687
  RunFunctionInTransaction([&]() {
101617
101688
  auto &catalog = Catalog::GetCatalog(*this);
101618
- ScalarFunctionCatalogEntry *existing_function = (ScalarFunctionCatalogEntry *)catalog.GetEntry(
101689
+ auto existing_function = (ScalarFunctionCatalogEntry *)catalog.GetEntry(
101619
101690
  *this, CatalogType::SCALAR_FUNCTION_ENTRY, info->schema, info->name, true);
101620
101691
  if (existing_function) {
101621
101692
  if (UpdateFunctionInfoFromEntry(existing_function, (CreateScalarFunctionInfo *)info)) {
@@ -101637,6 +101708,7 @@ void ClientContext::RunFunctionInTransactionInternal(ClientContextLock &lock, co
101637
101708
  // check if we are on AutoCommit. In this case we should start a transaction
101638
101709
  bool require_new_transaction = transaction.IsAutoCommit() && !transaction.HasActiveTransaction();
101639
101710
  if (require_new_transaction) {
101711
+ D_ASSERT(!active_query);
101640
101712
  transaction.BeginTransaction();
101641
101713
  }
101642
101714
  try {
@@ -101751,12 +101823,14 @@ unique_ptr<QueryResult> ClientContext::Execute(const shared_ptr<Relation> &relat
101751
101823
  // verify read only statements by running a select statement
101752
101824
  auto select = make_unique<SelectStatement>();
101753
101825
  select->node = relation->GetQueryNode();
101754
- RunStatement(*lock, query, move(select), false);
101826
+ RunStatementInternal(*lock, query, move(select), false);
101755
101827
  }
101756
101828
  }
101757
101829
  auto &expected_columns = relation->Columns();
101758
101830
  auto relation_stmt = make_unique<RelationStatement>(relation);
101759
- auto result = RunStatement(*lock, query, move(relation_stmt), false);
101831
+
101832
+ unique_ptr<QueryResult> result;
101833
+ result = RunStatementInternal(*lock, query, move(relation_stmt), false);
101760
101834
  if (!result->success) {
101761
101835
  return result;
101762
101836
  }
@@ -102528,10 +102602,11 @@ Connection::Connection(DuckDB &database) : Connection(*database.instance) {
102528
102602
  }
102529
102603
 
102530
102604
  string Connection::GetProfilingInformation(ProfilerPrintFormat format) {
102605
+ auto &profiler = QueryProfiler::Get(*context);
102531
102606
  if (format == ProfilerPrintFormat::JSON) {
102532
- return context->profiler->ToJSON();
102607
+ return profiler.ToJSON();
102533
102608
  } else {
102534
- return context->profiler->ToString();
102609
+ return profiler.ToString();
102535
102610
  }
102536
102611
  }
102537
102612
 
@@ -102575,6 +102650,14 @@ unique_ptr<MaterializedQueryResult> Connection::Query(unique_ptr<SQLStatement> s
102575
102650
  return unique_ptr_cast<QueryResult, MaterializedQueryResult>(move(result));
102576
102651
  }
102577
102652
 
102653
+ unique_ptr<PendingQueryResult> Connection::PendingQuery(const string &query) {
102654
+ return context->PendingQuery(query);
102655
+ }
102656
+
102657
+ unique_ptr<PendingQueryResult> Connection::PendingQuery(unique_ptr<SQLStatement> statement) {
102658
+ return context->PendingQuery(move(statement));
102659
+ }
102660
+
102578
102661
  unique_ptr<PreparedStatement> Connection::Prepare(const string &query) {
102579
102662
  return context->Prepare(query);
102580
102663
  }
@@ -110883,6 +110966,75 @@ unique_ptr<DataChunk> MaterializedQueryResult::FetchRaw() {
110883
110966
 
110884
110967
 
110885
110968
 
110969
+ namespace duckdb {
110970
+
110971
+ PendingQueryResult::PendingQueryResult(shared_ptr<ClientContext> context_p, PreparedStatementData &statement,
110972
+ vector<LogicalType> types_p)
110973
+ : BaseQueryResult(QueryResultType::PENDING_RESULT, statement.statement_type, move(types_p), statement.names),
110974
+ context(move(context_p)) {
110975
+ }
110976
+
110977
+ PendingQueryResult::PendingQueryResult(string error) : BaseQueryResult(QueryResultType::PENDING_RESULT, move(error)) {
110978
+ }
110979
+
110980
+ PendingQueryResult::~PendingQueryResult() {
110981
+ }
110982
+
110983
+ unique_ptr<ClientContextLock> PendingQueryResult::LockContext() {
110984
+ if (!context) {
110985
+ throw InvalidInputException("Attempting to execute an unsuccessful or closed pending query result\nError: %s",
110986
+ error);
110987
+ }
110988
+ return context->LockContext();
110989
+ }
110990
+
110991
+ void PendingQueryResult::CheckExecutableInternal(ClientContextLock &lock) {
110992
+ bool invalidated = !success || !context;
110993
+ if (!invalidated) {
110994
+ invalidated = !context->IsActiveResult(lock, this);
110995
+ }
110996
+ if (invalidated) {
110997
+ throw InvalidInputException("Attempting to execute an unsuccessful or closed pending query result\nError: %s",
110998
+ error);
110999
+ }
111000
+ }
111001
+
111002
+ PendingExecutionResult PendingQueryResult::ExecuteTask() {
111003
+ auto lock = LockContext();
111004
+ return ExecuteTaskInternal(*lock);
111005
+ }
111006
+
111007
+ PendingExecutionResult PendingQueryResult::ExecuteTaskInternal(ClientContextLock &lock) {
111008
+ CheckExecutableInternal(lock);
111009
+ return context->ExecuteTaskInternal(lock, *this);
111010
+ }
111011
+
111012
+ unique_ptr<QueryResult> PendingQueryResult::ExecuteInternal(ClientContextLock &lock, bool allow_streaming_result) {
111013
+ CheckExecutableInternal(lock);
111014
+ while (ExecuteTaskInternal(lock) == PendingExecutionResult::RESULT_NOT_READY) {
111015
+ }
111016
+ if (!success) {
111017
+ return make_unique<MaterializedQueryResult>(error);
111018
+ }
111019
+ auto result = context->FetchResultInternal(lock, *this, allow_streaming_result);
111020
+ Close();
111021
+ return result;
111022
+ }
111023
+
111024
+ unique_ptr<QueryResult> PendingQueryResult::Execute(bool allow_streaming_result) {
111025
+ auto lock = LockContext();
111026
+ return ExecuteInternal(*lock, allow_streaming_result);
111027
+ }
111028
+
111029
+ void PendingQueryResult::Close() {
111030
+ context.reset();
111031
+ }
111032
+
111033
+ } // namespace duckdb
111034
+
111035
+
111036
+
111037
+
110886
111038
 
110887
111039
  namespace duckdb {
110888
111040
 
@@ -110919,11 +111071,19 @@ const vector<string> &PreparedStatement::GetNames() {
110919
111071
  }
110920
111072
 
110921
111073
  unique_ptr<QueryResult> PreparedStatement::Execute(vector<Value> &values, bool allow_stream_result) {
111074
+ auto pending = PendingQuery(values);
111075
+ if (!pending->success) {
111076
+ return make_unique<MaterializedQueryResult>(pending->error);
111077
+ }
111078
+ return pending->Execute(allow_stream_result && data->allow_stream_result);
111079
+ }
111080
+
111081
+ unique_ptr<PendingQueryResult> PreparedStatement::PendingQuery(vector<Value> &values) {
110922
111082
  if (!success) {
110923
111083
  throw InvalidInputException("Attempting to execute an unsuccessfully prepared statement!");
110924
111084
  }
110925
111085
  D_ASSERT(data);
110926
- auto result = context->Execute(query, data, values, allow_stream_result && data->allow_stream_result);
111086
+ auto result = context->PendingQuery(query, data, values);
110927
111087
  return result;
110928
111088
  }
110929
111089
 
@@ -111009,16 +111169,42 @@ using std::ofstream;
111009
111169
 
111010
111170
 
111011
111171
 
111172
+
111173
+
111012
111174
  #include <utility>
111013
111175
  #include <algorithm>
111014
111176
 
111015
111177
  namespace duckdb {
111016
111178
 
111179
+ QueryProfiler::QueryProfiler(ClientContext &context_p)
111180
+ : context(context_p), running(false), query_requires_profiling(false), is_explain_analyze(false) {
111181
+ }
111182
+
111183
+ bool QueryProfiler::IsEnabled() const {
111184
+ return is_explain_analyze ? true : ClientConfig::GetConfig(context).enable_profiler;
111185
+ }
111186
+
111187
+ bool QueryProfiler::IsDetailedEnabled() const {
111188
+ return is_explain_analyze ? false : ClientConfig::GetConfig(context).enable_detailed_profiling;
111189
+ }
111190
+
111191
+ ProfilerPrintFormat QueryProfiler::GetPrintFormat() const {
111192
+ return is_explain_analyze ? ProfilerPrintFormat::NONE : ClientConfig::GetConfig(context).profiler_print_format;
111193
+ }
111194
+
111195
+ string QueryProfiler::GetSaveLocation() const {
111196
+ return is_explain_analyze ? string() : ClientConfig::GetConfig(context).profiler_save_location;
111197
+ }
111198
+
111199
+ QueryProfiler &QueryProfiler::Get(ClientContext &context) {
111200
+ return *context.profiler;
111201
+ }
111202
+
111017
111203
  void QueryProfiler::StartQuery(string query, bool is_explain_analyze) {
111018
111204
  if (is_explain_analyze) {
111019
111205
  StartExplainAnalyze();
111020
111206
  }
111021
- if (!enabled) {
111207
+ if (!IsEnabled()) {
111022
111208
  return;
111023
111209
  }
111024
111210
  this->running = true;
@@ -111076,17 +111262,10 @@ void QueryProfiler::Finalize(TreeNode &node) {
111076
111262
 
111077
111263
  void QueryProfiler::StartExplainAnalyze() {
111078
111264
  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
111265
  }
111087
111266
 
111088
111267
  void QueryProfiler::EndQuery() {
111089
- if (!enabled || !running) {
111268
+ if (!IsEnabled() || !running) {
111090
111269
  return;
111091
111270
  }
111092
111271
 
@@ -111095,6 +111274,7 @@ void QueryProfiler::EndQuery() {
111095
111274
  Finalize(*root);
111096
111275
  }
111097
111276
  this->running = false;
111277
+ auto automatic_print_format = GetPrintFormat();
111098
111278
  // print or output the query profiling after termination, if this is enabled
111099
111279
  if (automatic_print_format != ProfilerPrintFormat::NONE) {
111100
111280
  // check if this query should be output based on the operator types
@@ -111106,7 +111286,7 @@ void QueryProfiler::EndQuery() {
111106
111286
  } else if (automatic_print_format == ProfilerPrintFormat::QUERY_TREE_OPTIMIZER) {
111107
111287
  query_info = ToString(true);
111108
111288
  }
111109
-
111289
+ auto save_location = GetSaveLocation();
111110
111290
  if (save_location.empty()) {
111111
111291
  Printer::Print(query_info);
111112
111292
  Printer::Print("\n");
@@ -111114,16 +111294,11 @@ void QueryProfiler::EndQuery() {
111114
111294
  WriteToFile(save_location.c_str(), query_info);
111115
111295
  }
111116
111296
  }
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
- }
111297
+ this->is_explain_analyze = false;
111123
111298
  }
111124
111299
 
111125
111300
  void QueryProfiler::StartPhase(string new_phase) {
111126
- if (!enabled || !running) {
111301
+ if (!IsEnabled() || !running) {
111127
111302
  return;
111128
111303
  }
111129
111304
 
@@ -111147,7 +111322,7 @@ void QueryProfiler::StartPhase(string new_phase) {
111147
111322
  }
111148
111323
 
111149
111324
  void QueryProfiler::EndPhase() {
111150
- if (!enabled || !running) {
111325
+ if (!IsEnabled() || !running) {
111151
111326
  return;
111152
111327
  }
111153
111328
  D_ASSERT(phase_stack.size() > 0);
@@ -111167,7 +111342,7 @@ void QueryProfiler::EndPhase() {
111167
111342
  }
111168
111343
 
111169
111344
  void QueryProfiler::Initialize(PhysicalOperator *root_op) {
111170
- if (!enabled || !running) {
111345
+ if (!IsEnabled() || !running) {
111171
111346
  return;
111172
111347
  }
111173
111348
  this->query_requires_profiling = false;
@@ -111248,7 +111423,7 @@ void OperatorProfiler::Flush(const PhysicalOperator *phys_op, ExpressionExecutor
111248
111423
  }
111249
111424
 
111250
111425
  void QueryProfiler::Flush(OperatorProfiler &profiler) {
111251
- if (!enabled || !running) {
111426
+ if (!IsEnabled() || !running) {
111252
111427
  return;
111253
111428
  }
111254
111429
  lock_guard<mutex> guard(flush_lock);
@@ -111258,7 +111433,7 @@ void QueryProfiler::Flush(OperatorProfiler &profiler) {
111258
111433
 
111259
111434
  entry->second->info.time += node.second.time;
111260
111435
  entry->second->info.elements += node.second.elements;
111261
- if (!detailed_enabled) {
111436
+ if (!IsDetailedEnabled()) {
111262
111437
  continue;
111263
111438
  }
111264
111439
  for (auto &info : node.second.executors_info) {
@@ -111319,7 +111494,7 @@ string QueryProfiler::ToString(bool print_optimizer_output) const {
111319
111494
  }
111320
111495
 
111321
111496
  void QueryProfiler::ToStream(std::ostream &ss, bool print_optimizer_output) const {
111322
- if (!enabled) {
111497
+ if (!IsEnabled()) {
111323
111498
  ss << "Query profiling is disabled. Call "
111324
111499
  "Connection::EnableProfiling() to enable profiling!";
111325
111500
  return;
@@ -111490,7 +111665,7 @@ static void ToJSONRecursive(QueryProfiler::TreeNode &node, std::ostream &ss, int
111490
111665
  }
111491
111666
 
111492
111667
  string QueryProfiler::ToJSON() const {
111493
- if (!enabled) {
111668
+ if (!IsEnabled()) {
111494
111669
  return "{ \"result\": \"disabled\" }\n";
111495
111670
  }
111496
111671
  if (query.empty()) {
@@ -111605,10 +111780,6 @@ vector<QueryProfiler::PhaseTimingItem> QueryProfiler::GetOrderedPhaseTimings() c
111605
111780
  return result;
111606
111781
  }
111607
111782
  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
111783
  }
111613
111784
 
111614
111785
  void ExpressionInfo::ExtractExpressionsRecursive(unique_ptr<ExpressionState> &state) {
@@ -111665,17 +111836,44 @@ ExpressionRootInfo::ExpressionRootInfo(ExpressionExecutorState &state, string na
111665
111836
 
111666
111837
  namespace duckdb {
111667
111838
 
111668
- QueryResult::QueryResult(QueryResultType type, StatementType statement_type)
111839
+ BaseQueryResult::BaseQueryResult(QueryResultType type, StatementType statement_type)
111669
111840
  : type(type), statement_type(statement_type), success(true) {
111670
111841
  }
111671
111842
 
111672
- QueryResult::QueryResult(QueryResultType type, StatementType statement_type, vector<LogicalType> types_p,
111673
- vector<string> names_p)
111843
+ BaseQueryResult::BaseQueryResult(QueryResultType type, StatementType statement_type, vector<LogicalType> types_p,
111844
+ vector<string> names_p)
111674
111845
  : type(type), statement_type(statement_type), types(move(types_p)), names(move(names_p)), success(true) {
111675
111846
  D_ASSERT(types.size() == names.size());
111676
111847
  }
111677
111848
 
111678
- QueryResult::QueryResult(QueryResultType type, string error) : type(type), success(false), error(move(error)) {
111849
+ BaseQueryResult::BaseQueryResult(QueryResultType type, string error) : type(type), success(false), error(move(error)) {
111850
+ }
111851
+
111852
+ BaseQueryResult::~BaseQueryResult() {
111853
+ }
111854
+
111855
+ bool BaseQueryResult::HasError() {
111856
+ return !success;
111857
+ }
111858
+ const string &BaseQueryResult::GetError() {
111859
+ return error;
111860
+ }
111861
+ idx_t BaseQueryResult::ColumnCount() {
111862
+ return types.size();
111863
+ }
111864
+
111865
+ QueryResult::QueryResult(QueryResultType type, StatementType statement_type) : BaseQueryResult(type, statement_type) {
111866
+ }
111867
+
111868
+ QueryResult::QueryResult(QueryResultType type, StatementType statement_type, vector<LogicalType> types_p,
111869
+ vector<string> names_p)
111870
+ : BaseQueryResult(type, statement_type, move(types_p), move(names_p)) {
111871
+ }
111872
+
111873
+ QueryResult::QueryResult(QueryResultType type, string error) : BaseQueryResult(type, move(error)) {
111874
+ }
111875
+
111876
+ QueryResult::~QueryResult() {
111679
111877
  }
111680
111878
 
111681
111879
  unique_ptr<DataChunk> QueryResult::Fetch() {
@@ -114694,24 +114892,27 @@ Value EnableObjectCacheSetting::GetSetting(ClientContext &context) {
114694
114892
  //===--------------------------------------------------------------------===//
114695
114893
  void EnableProfilingSetting::SetLocal(ClientContext &context, const Value &input) {
114696
114894
  auto parameter = StringUtil::Lower(input.ToString());
114895
+
114896
+ auto &config = ClientConfig::GetConfig(context);
114697
114897
  if (parameter == "json") {
114698
- context.profiler->automatic_print_format = ProfilerPrintFormat::JSON;
114898
+ config.profiler_print_format = ProfilerPrintFormat::JSON;
114699
114899
  } else if (parameter == "query_tree") {
114700
- context.profiler->automatic_print_format = ProfilerPrintFormat::QUERY_TREE;
114900
+ config.profiler_print_format = ProfilerPrintFormat::QUERY_TREE;
114701
114901
  } else if (parameter == "query_tree_optimizer") {
114702
- context.profiler->automatic_print_format = ProfilerPrintFormat::QUERY_TREE_OPTIMIZER;
114902
+ config.profiler_print_format = ProfilerPrintFormat::QUERY_TREE_OPTIMIZER;
114703
114903
  } else {
114704
114904
  throw ParserException(
114705
114905
  "Unrecognized print format %s, supported formats: [json, query_tree, query_tree_optimizer]", parameter);
114706
114906
  }
114707
- context.profiler->Enable();
114907
+ config.enable_profiler = true;
114708
114908
  }
114709
114909
 
114710
114910
  Value EnableProfilingSetting::GetSetting(ClientContext &context) {
114711
- if (!context.profiler->IsEnabled()) {
114911
+ auto &config = ClientConfig::GetConfig(context);
114912
+ if (!config.enable_profiler) {
114712
114913
  return Value();
114713
114914
  }
114714
- switch (context.profiler->automatic_print_format) {
114915
+ switch (config.profiler_print_format) {
114715
114916
  case ProfilerPrintFormat::NONE:
114716
114917
  return Value("none");
114717
114918
  case ProfilerPrintFormat::JSON:
@@ -114855,12 +115056,14 @@ Value ProfilerHistorySize::GetSetting(ClientContext &context) {
114855
115056
  // Profile Output
114856
115057
  //===--------------------------------------------------------------------===//
114857
115058
  void ProfileOutputSetting::SetLocal(ClientContext &context, const Value &input) {
115059
+ auto &config = ClientConfig::GetConfig(context);
114858
115060
  auto parameter = input.ToString();
114859
- context.profiler->save_location = parameter;
115061
+ config.profiler_save_location = parameter;
114860
115062
  }
114861
115063
 
114862
115064
  Value ProfileOutputSetting::GetSetting(ClientContext &context) {
114863
- return Value(context.profiler->save_location);
115065
+ auto &config = ClientConfig::GetConfig(context);
115066
+ return Value(config.profiler_save_location);
114864
115067
  }
114865
115068
 
114866
115069
  //===--------------------------------------------------------------------===//
@@ -114868,17 +115071,24 @@ Value ProfileOutputSetting::GetSetting(ClientContext &context) {
114868
115071
  //===--------------------------------------------------------------------===//
114869
115072
  void ProfilingModeSetting::SetLocal(ClientContext &context, const Value &input) {
114870
115073
  auto parameter = StringUtil::Lower(input.ToString());
115074
+ auto &config = ClientConfig::GetConfig(context);
114871
115075
  if (parameter == "standard") {
114872
- context.profiler->Enable();
115076
+ config.enable_profiler = true;
115077
+ config.enable_detailed_profiling = false;
114873
115078
  } else if (parameter == "detailed") {
114874
- context.profiler->DetailedEnable();
115079
+ config.enable_profiler = true;
115080
+ config.enable_detailed_profiling = true;
114875
115081
  } else {
114876
115082
  throw ParserException("Unrecognized profiling mode \"%s\", supported formats: [standard, detailed]", parameter);
114877
115083
  }
114878
115084
  }
114879
115085
 
114880
115086
  Value ProfilingModeSetting::GetSetting(ClientContext &context) {
114881
- return Value(context.profiler->IsDetailedEnabled() ? "detailed" : "standard");
115087
+ auto &config = ClientConfig::GetConfig(context);
115088
+ if (!config.enable_profiler) {
115089
+ return Value();
115090
+ }
115091
+ return Value(config.enable_detailed_profiling ? "detailed" : "standard");
114882
115092
  }
114883
115093
 
114884
115094
  //===--------------------------------------------------------------------===//
@@ -114958,14 +115168,11 @@ Value ThreadsSetting::GetSetting(ClientContext &context) {
114958
115168
  namespace duckdb {
114959
115169
 
114960
115170
  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)) {
115171
+ vector<LogicalType> types, vector<string> names)
115172
+ : QueryResult(QueryResultType::STREAM_RESULT, statement_type, move(types), move(names)), context(move(context)) {
114965
115173
  }
114966
115174
 
114967
115175
  StreamQueryResult::~StreamQueryResult() {
114968
- Close();
114969
115176
  }
114970
115177
 
114971
115178
  string StreamQueryResult::ToString() {
@@ -114979,12 +115186,28 @@ string StreamQueryResult::ToString() {
114979
115186
  return result;
114980
115187
  }
114981
115188
 
115189
+ unique_ptr<ClientContextLock> StreamQueryResult::LockContext() {
115190
+ if (!context) {
115191
+ throw InvalidInputException("Attempting to execute an unsuccessful or closed pending query result\nError: %s",
115192
+ error);
115193
+ }
115194
+ return context->LockContext();
115195
+ }
115196
+
115197
+ void StreamQueryResult::CheckExecutableInternal(ClientContextLock &lock) {
115198
+ if (!IsOpenInternal(lock)) {
115199
+ throw InvalidInputException("Attempting to execute an unsuccessful or closed pending query result\nError: %s",
115200
+ error);
115201
+ }
115202
+ }
115203
+
114982
115204
  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);
115205
+ unique_ptr<DataChunk> chunk;
115206
+ {
115207
+ auto lock = LockContext();
115208
+ CheckExecutableInternal(*lock);
115209
+ chunk = context->Fetch(*lock, *this);
114986
115210
  }
114987
- auto chunk = context->Fetch();
114988
115211
  if (!chunk || chunk->ColumnCount() == 0 || chunk->size() == 0) {
114989
115212
  Close();
114990
115213
  return nullptr;
@@ -115010,12 +115233,24 @@ unique_ptr<MaterializedQueryResult> StreamQueryResult::Materialize() {
115010
115233
  return result;
115011
115234
  }
115012
115235
 
115013
- void StreamQueryResult::Close() {
115014
- if (!is_open) {
115015
- return;
115236
+ bool StreamQueryResult::IsOpenInternal(ClientContextLock &lock) {
115237
+ bool invalidated = !success || !context;
115238
+ if (!invalidated) {
115239
+ invalidated = !context->IsActiveResult(lock, this);
115016
115240
  }
115017
- is_open = false;
115018
- context->Cleanup();
115241
+ return !invalidated;
115242
+ }
115243
+
115244
+ bool StreamQueryResult::IsOpen() {
115245
+ if (!success || !context) {
115246
+ return false;
115247
+ }
115248
+ auto lock = LockContext();
115249
+ return IsOpenInternal(*lock);
115250
+ }
115251
+
115252
+ void StreamQueryResult::Close() {
115253
+ context.reset();
115019
115254
  }
115020
115255
 
115021
115256
  } // namespace duckdb
@@ -119810,9 +120045,10 @@ void Optimizer::RunOptimizer(OptimizerType type, const std::function<void()> &ca
119810
120045
  // optimizer is marked as disabled: skip
119811
120046
  return;
119812
120047
  }
119813
- context.profiler->StartPhase(OptimizerTypeToString(type));
120048
+ auto &profiler = QueryProfiler::Get(context);
120049
+ profiler.StartPhase(OptimizerTypeToString(type));
119814
120050
  callback();
119815
- context.profiler->EndPhase();
120051
+ profiler.EndPhase();
119816
120052
  }
119817
120053
 
119818
120054
  unique_ptr<LogicalOperator> Optimizer::Optimize(unique_ptr<LogicalOperator> plan) {
@@ -123771,6 +124007,10 @@ public:
123771
124007
 
123772
124008
  //! Fully execute a pipeline with a source and a sink until the source is completely exhausted
123773
124009
  void Execute();
124010
+ //! Execute a pipeline with a source and a sink until finished, or until max_chunks have been processed
124011
+ //! Returns true if execution is finished, false if Execute should be called again
124012
+ bool Execute(idx_t max_chunks);
124013
+
123774
124014
  //! Push a single input DataChunk into the pipeline.
123775
124015
  //! Returns either OperatorResultType::NEED_MORE_INPUT or OperatorResultType::FINISHED
123776
124016
  //! If OperatorResultType::FINISHED is returned, more input will not change the result anymore
@@ -123939,7 +124179,7 @@ Executor::~Executor() {
123939
124179
  }
123940
124180
 
123941
124181
  Executor &Executor::Get(ClientContext &context) {
123942
- return context.executor;
124182
+ return context.GetExecutor();
123943
124183
  }
123944
124184
 
123945
124185
  void Executor::AddEvent(shared_ptr<Event> event) {
@@ -124168,16 +124408,6 @@ void Executor::VerifyPipelines() {
124168
124408
  #endif
124169
124409
  }
124170
124410
 
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
124411
  void Executor::Initialize(PhysicalOperator *plan) {
124182
124412
  Reset();
124183
124413
 
@@ -124186,7 +124416,8 @@ void Executor::Initialize(PhysicalOperator *plan) {
124186
124416
  lock_guard<mutex> elock(executor_lock);
124187
124417
  physical_plan = plan;
124188
124418
 
124189
- context.profiler->Initialize(physical_plan);
124419
+ auto &profiler = QueryProfiler::Get(context);
124420
+ profiler.Initialize(physical_plan);
124190
124421
  this->producer = scheduler.CreateProducer();
124191
124422
 
124192
124423
  auto root_pipeline = make_shared<Pipeline>(*this);
@@ -124202,60 +124433,102 @@ void Executor::Initialize(PhysicalOperator *plan) {
124202
124433
 
124203
124434
  ScheduleEvents();
124204
124435
  }
124436
+ }
124205
124437
 
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;
124438
+ void Executor::CancelTasks() {
124439
+ task.reset();
124440
+ // we do this by creating weak pointers to all pipelines
124441
+ // then clearing our references to the pipelines
124442
+ // and waiting until all pipelines have been destroyed
124443
+ vector<weak_ptr<Pipeline>> weak_references;
124444
+ {
124445
+ lock_guard<mutex> elock(executor_lock);
124446
+ if (pipelines.empty()) {
124447
+ return;
124212
124448
  }
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) {
124449
+ weak_references.reserve(pipelines.size());
124450
+ for (auto &pipeline : pipelines) {
124451
+ weak_references.push_back(weak_ptr<Pipeline>(pipeline));
124452
+ }
124453
+ for (auto &kv : union_pipelines) {
124454
+ for (auto &pipeline : kv.second) {
124224
124455
  weak_references.push_back(weak_ptr<Pipeline>(pipeline));
124225
124456
  }
124226
- for (auto &kv : union_pipelines) {
124227
- for (auto &pipeline : kv.second) {
124228
- weak_references.push_back(weak_ptr<Pipeline>(pipeline));
124229
- }
124457
+ }
124458
+ for (auto &kv : child_pipelines) {
124459
+ for (auto &pipeline : kv.second) {
124460
+ weak_references.push_back(weak_ptr<Pipeline>(pipeline));
124230
124461
  }
124231
- for (auto &kv : child_pipelines) {
124232
- for (auto &pipeline : kv.second) {
124233
- weak_references.push_back(weak_ptr<Pipeline>(pipeline));
124234
- }
124462
+ }
124463
+ pipelines.clear();
124464
+ union_pipelines.clear();
124465
+ child_pipelines.clear();
124466
+ events.clear();
124467
+ }
124468
+ WorkOnTasks();
124469
+ for (auto &weak_ref : weak_references) {
124470
+ while (true) {
124471
+ auto weak = weak_ref.lock();
124472
+ if (!weak) {
124473
+ break;
124235
124474
  }
124236
- pipelines.clear();
124237
- union_pipelines.clear();
124238
- child_pipelines.clear();
124239
- events.clear();
124240
124475
  }
124241
- for (auto &weak_ref : weak_references) {
124242
- while (true) {
124243
- auto weak = weak_ref.lock();
124244
- if (!weak) {
124245
- break;
124246
- }
124476
+ }
124477
+ }
124478
+
124479
+ void Executor::WorkOnTasks() {
124480
+ auto &scheduler = TaskScheduler::GetScheduler(context);
124481
+
124482
+ unique_ptr<Task> task;
124483
+ while (scheduler.GetTaskFromProducer(*producer, task)) {
124484
+ task->Execute(TaskExecutionMode::PROCESS_ALL);
124485
+ task.reset();
124486
+ }
124487
+ }
124488
+
124489
+ PendingExecutionResult Executor::ExecuteTask() {
124490
+ if (execution_result != PendingExecutionResult::RESULT_NOT_READY) {
124491
+ return execution_result;
124492
+ }
124493
+ // check if there are any incomplete pipelines
124494
+ auto &scheduler = TaskScheduler::GetScheduler(context);
124495
+ while (completed_pipelines < total_pipelines) {
124496
+ // there are! if we don't already have a task, fetch one
124497
+ if (!task) {
124498
+ scheduler.GetTaskFromProducer(*producer, task);
124499
+ }
124500
+ if (task) {
124501
+ // if we have a task, partially process it
124502
+ auto result = task->Execute(TaskExecutionMode::PROCESS_PARTIAL);
124503
+ if (result != TaskExecutionResult::TASK_NOT_FINISHED) {
124504
+ // if the task is finished, clean it up
124505
+ task.reset();
124247
124506
  }
124248
124507
  }
124508
+ if (!HasError()) {
124509
+ // we (partially) processed a task and no exceptions were thrown
124510
+ // give back control to the caller
124511
+ return PendingExecutionResult::RESULT_NOT_READY;
124512
+ }
124513
+ execution_result = PendingExecutionResult::EXECUTION_ERROR;
124514
+
124515
+ // an exception has occurred executing one of the pipelines
124516
+ // we need to cancel all tasks associated with this executor
124517
+ CancelTasks();
124249
124518
  ThrowException();
124250
124519
  }
124520
+ D_ASSERT(!task);
124251
124521
 
124252
124522
  lock_guard<mutex> elock(executor_lock);
124253
124523
  pipelines.clear();
124254
124524
  NextExecutor();
124255
124525
  if (!exceptions.empty()) { // LCOV_EXCL_START
124256
124526
  // an exception has occurred executing one of the pipelines
124527
+ execution_result = PendingExecutionResult::EXECUTION_ERROR;
124257
124528
  ThrowExceptionInternal();
124258
124529
  } // LCOV_EXCL_STOP
124530
+ execution_result = PendingExecutionResult::RESULT_READY;
124531
+ return execution_result;
124259
124532
  }
124260
124533
 
124261
124534
  void Executor::Reset() {
@@ -124274,6 +124547,7 @@ void Executor::Reset() {
124274
124547
  union_pipelines.clear();
124275
124548
  child_pipelines.clear();
124276
124549
  child_dependencies.clear();
124550
+ execution_result = PendingExecutionResult::RESULT_NOT_READY;
124277
124551
  }
124278
124552
 
124279
124553
  void Executor::AddChildPipeline(Pipeline *current) {
@@ -124555,10 +124829,11 @@ void Executor::ThrowExceptionInternal() { // LCOV_EXCL_START
124555
124829
 
124556
124830
  void Executor::Flush(ThreadContext &tcontext) {
124557
124831
  lock_guard<mutex> elock(executor_lock);
124558
- context.profiler->Flush(tcontext.profiler);
124832
+ auto &profiler = QueryProfiler::Get(context);
124833
+ profiler.Flush(tcontext.profiler);
124559
124834
  }
124560
124835
 
124561
- bool Executor::GetPipelinesProgress(int &current_progress) { // LCOV_EXCL_START
124836
+ bool Executor::GetPipelinesProgress(double &current_progress) { // LCOV_EXCL_START
124562
124837
  lock_guard<mutex> elock(executor_lock);
124563
124838
 
124564
124839
  if (!pipelines.empty()) {
@@ -124604,9 +124879,9 @@ ExecutorTask::ExecutorTask(ClientContext &context) : ExecutorTask(Executor::Get(
124604
124879
  ExecutorTask::~ExecutorTask() {
124605
124880
  }
124606
124881
 
124607
- void ExecutorTask::Execute() {
124882
+ TaskExecutionResult ExecutorTask::Execute(TaskExecutionMode mode) {
124608
124883
  try {
124609
- ExecuteTask();
124884
+ return ExecuteTask(mode);
124610
124885
  } catch (Exception &ex) {
124611
124886
  executor.PushError(ex.type, ex.what());
124612
124887
  } catch (std::exception &ex) {
@@ -124614,6 +124889,7 @@ void ExecutorTask::Execute() {
124614
124889
  } catch (...) { // LCOV_EXCL_START
124615
124890
  executor.PushError(ExceptionType::UNKNOWN_TYPE, "Unknown exception in Finalize!");
124616
124891
  } // LCOV_EXCL_STOP
124892
+ return TaskExecutionResult::TASK_ERROR;
124617
124893
  }
124618
124894
 
124619
124895
  } // namespace duckdb
@@ -124641,6 +124917,8 @@ void ExecutorTask::Execute() {
124641
124917
  namespace duckdb {
124642
124918
 
124643
124919
  class PipelineTask : public ExecutorTask {
124920
+ static constexpr const idx_t PARTIAL_CHUNK_COUNT = 50;
124921
+
124644
124922
  public:
124645
124923
  explicit PipelineTask(Pipeline &pipeline_p, shared_ptr<Event> event_p)
124646
124924
  : ExecutorTask(pipeline_p.executor), pipeline(pipeline_p), event(move(event_p)) {
@@ -124648,12 +124926,24 @@ public:
124648
124926
 
124649
124927
  Pipeline &pipeline;
124650
124928
  shared_ptr<Event> event;
124929
+ unique_ptr<PipelineExecutor> pipeline_executor;
124651
124930
 
124652
124931
  public:
124653
- void ExecuteTask() override {
124654
- PipelineExecutor executor(pipeline.GetClientContext(), pipeline);
124655
- executor.Execute();
124932
+ TaskExecutionResult ExecuteTask(TaskExecutionMode mode) override {
124933
+ if (!pipeline_executor) {
124934
+ pipeline_executor = make_unique<PipelineExecutor>(pipeline.GetClientContext(), pipeline);
124935
+ }
124936
+ if (mode == TaskExecutionMode::PROCESS_PARTIAL) {
124937
+ bool finished = pipeline_executor->Execute(PARTIAL_CHUNK_COUNT);
124938
+ if (!finished) {
124939
+ return TaskExecutionResult::TASK_NOT_FINISHED;
124940
+ }
124941
+ } else {
124942
+ pipeline_executor->Execute();
124943
+ }
124656
124944
  event->FinishTask();
124945
+ pipeline_executor.reset();
124946
+ return TaskExecutionResult::TASK_FINISHED;
124657
124947
  }
124658
124948
  };
124659
124949
 
@@ -124665,7 +124955,7 @@ ClientContext &Pipeline::GetClientContext() {
124665
124955
  }
124666
124956
 
124667
124957
  // LCOV_EXCL_START
124668
- bool Pipeline::GetProgressInternal(ClientContext &context, PhysicalOperator *op, int &current_percentage) {
124958
+ bool Pipeline::GetProgressInternal(ClientContext &context, PhysicalOperator *op, double &current_percentage) {
124669
124959
  current_percentage = -1;
124670
124960
  switch (op->type) {
124671
124961
  case PhysicalOperatorType::TABLE_SCAN: {
@@ -124684,7 +124974,7 @@ bool Pipeline::GetProgressInternal(ClientContext &context, PhysicalOperator *op,
124684
124974
  }
124685
124975
  // LCOV_EXCL_STOP
124686
124976
 
124687
- bool Pipeline::GetProgress(int &current_percentage) {
124977
+ bool Pipeline::GetProgress(double &current_percentage) {
124688
124978
  auto &client = executor.context;
124689
124979
  return GetProgressInternal(client, source, current_percentage);
124690
124980
  }
@@ -124885,16 +125175,18 @@ PipelineExecutor::PipelineExecutor(ClientContext &context_p, Pipeline &pipeline_
124885
125175
  InitializeChunk(final_chunk);
124886
125176
  }
124887
125177
 
124888
- void PipelineExecutor::Execute() {
125178
+ bool PipelineExecutor::Execute(idx_t max_chunks) {
124889
125179
  D_ASSERT(pipeline.sink);
125180
+ bool exhausted_source = false;
124890
125181
  auto &source_chunk = pipeline.operators.empty() ? final_chunk : *intermediate_chunks[0];
124891
- while (true) {
125182
+ for (idx_t i = 0; i < max_chunks; i++) {
124892
125183
  if (finished_processing) {
124893
125184
  break;
124894
125185
  }
124895
125186
  source_chunk.Reset();
124896
125187
  FetchFromSource(source_chunk);
124897
125188
  if (source_chunk.size() == 0) {
125189
+ exhausted_source = true;
124898
125190
  break;
124899
125191
  }
124900
125192
  auto result = ExecutePushInternal(source_chunk);
@@ -124903,7 +125195,15 @@ void PipelineExecutor::Execute() {
124903
125195
  break;
124904
125196
  }
124905
125197
  }
125198
+ if (!exhausted_source && !finished_processing) {
125199
+ return false;
125200
+ }
124906
125201
  PushFinalize();
125202
+ return true;
125203
+ }
125204
+
125205
+ void PipelineExecutor::Execute() {
125206
+ Execute(NumericLimits<idx_t>::Maximum());
124907
125207
  }
124908
125208
 
124909
125209
  OperatorResultType PipelineExecutor::ExecutePush(DataChunk &input) { // LCOV_EXCL_START
@@ -129434,7 +129734,7 @@ void TaskScheduler::ExecuteForever(atomic<bool> *marker) {
129434
129734
  // wait for a signal with a timeout; the timeout allows us to periodically check
129435
129735
  queue->semaphore.wait(TASK_TIMEOUT_USECS);
129436
129736
  if (queue->q.try_dequeue(task)) {
129437
- task->Execute();
129737
+ task->Execute(TaskExecutionMode::PROCESS_ALL);
129438
129738
  task.reset();
129439
129739
  }
129440
129740
  }
@@ -129507,7 +129807,7 @@ void TaskScheduler::SetThreadsInternal(int32_t n) {
129507
129807
 
129508
129808
  namespace duckdb {
129509
129809
 
129510
- ThreadContext::ThreadContext(ClientContext &context) : profiler(context.profiler->IsEnabled()) {
129810
+ ThreadContext::ThreadContext(ClientContext &context) : profiler(QueryProfiler::Get(context).IsEnabled()) {
129511
129811
  }
129512
129812
 
129513
129813
  } // namespace duckdb
@@ -154511,13 +154811,15 @@ Planner::Planner(ClientContext &context) : binder(Binder::CreateBinder(context))
154511
154811
  }
154512
154812
 
154513
154813
  void Planner::CreatePlan(SQLStatement &statement) {
154814
+ auto &profiler = QueryProfiler::Get(context);
154815
+
154514
154816
  vector<BoundParameterExpression *> bound_parameters;
154515
154817
 
154516
154818
  // first bind the tables and columns to the catalog
154517
- context.profiler->StartPhase("binder");
154819
+ profiler.StartPhase("binder");
154518
154820
  binder->parameters = &bound_parameters;
154519
154821
  auto bound_statement = binder->Bind(statement);
154520
- context.profiler->EndPhase();
154822
+ profiler.EndPhase();
154521
154823
 
154522
154824
  this->read_only = binder->read_only;
154523
154825
  this->requires_valid_transaction = binder->requires_valid_transaction;