duckdb 0.4.1-dev1016.0 → 0.4.1-dev1022.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "duckdb",
3
3
  "main": "./lib/duckdb.js",
4
- "version": "0.4.1-dev1016.0",
4
+ "version": "0.4.1-dev1022.0",
5
5
  "description": "DuckDB node.js API",
6
6
  "gypfile": true,
7
7
  "dependencies": {
package/src/duckdb.cpp CHANGED
@@ -79499,18 +79499,21 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalWindow &op
79499
79499
  types.resize(output_idx);
79500
79500
 
79501
79501
  // Identify streaming windows
79502
- vector<idx_t> window_expressions;
79503
- bool process_streaming = true;
79502
+ vector<idx_t> blocking_windows;
79503
+ vector<idx_t> streaming_windows;
79504
79504
  for (idx_t expr_idx = 0; expr_idx < op.expressions.size(); expr_idx++) {
79505
- window_expressions.push_back(expr_idx);
79506
- if (!IsStreamingWindow(op.expressions[expr_idx])) {
79507
- process_streaming = false;
79505
+ if (IsStreamingWindow(op.expressions[expr_idx])) {
79506
+ streaming_windows.push_back(expr_idx);
79507
+ } else {
79508
+ blocking_windows.push_back(expr_idx);
79508
79509
  }
79509
79510
  }
79511
+
79510
79512
  // Process the window functions by sharing the partition/order definitions
79511
79513
  vector<idx_t> evaluation_order;
79512
- while (!window_expressions.empty()) {
79513
- auto &remaining = window_expressions;
79514
+ while (!blocking_windows.empty() || !streaming_windows.empty()) {
79515
+ const bool process_streaming = blocking_windows.empty();
79516
+ auto &remaining = process_streaming ? streaming_windows : blocking_windows;
79514
79517
 
79515
79518
  // Find all functions that share the partitioning of the first remaining expression
79516
79519
  const auto over_idx = remaining[0];
@@ -79547,7 +79550,7 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalWindow &op
79547
79550
  plan = move(window);
79548
79551
 
79549
79552
  // Remember the projection order if we changed it
79550
- if (!remaining.empty() || !evaluation_order.empty()) {
79553
+ if (!streaming_windows.empty() || !blocking_windows.empty() || !evaluation_order.empty()) {
79551
79554
  evaluation_order.insert(evaluation_order.end(), matching.begin(), matching.end());
79552
79555
  }
79553
79556
  }
@@ -116654,6 +116657,16 @@ void duckdb_function_set_error(duckdb_function_info info, const char *error) {
116654
116657
 
116655
116658
  using duckdb::DatabaseData;
116656
116659
 
116660
+ struct CAPITaskState {
116661
+ CAPITaskState(duckdb::DatabaseInstance &db)
116662
+ : db(db), marker(duckdb::make_unique<duckdb::atomic<bool>>(true)), execute_count(0) {
116663
+ }
116664
+
116665
+ duckdb::DatabaseInstance &db;
116666
+ duckdb::unique_ptr<duckdb::atomic<bool>> marker;
116667
+ duckdb::atomic<idx_t> execute_count;
116668
+ };
116669
+
116657
116670
  void duckdb_execute_tasks(duckdb_database database, idx_t max_tasks) {
116658
116671
  if (!database) {
116659
116672
  return;
@@ -116663,6 +116676,46 @@ void duckdb_execute_tasks(duckdb_database database, idx_t max_tasks) {
116663
116676
  scheduler.ExecuteTasks(max_tasks);
116664
116677
  }
116665
116678
 
116679
+ duckdb_task_state duckdb_create_task_state(duckdb_database database) {
116680
+ if (!database) {
116681
+ return nullptr;
116682
+ }
116683
+ auto wrapper = (DatabaseData *)database;
116684
+ auto state = new CAPITaskState(*wrapper->database->instance);
116685
+ return state;
116686
+ }
116687
+
116688
+ void duckdb_execute_tasks_state(duckdb_task_state state_p) {
116689
+ if (!state_p) {
116690
+ return;
116691
+ }
116692
+ auto state = (CAPITaskState *)state_p;
116693
+ auto &scheduler = duckdb::TaskScheduler::GetScheduler(state->db);
116694
+ state->execute_count++;
116695
+ scheduler.ExecuteForever(state->marker.get());
116696
+ }
116697
+
116698
+ void duckdb_finish_execution(duckdb_task_state state_p) {
116699
+ if (!state_p) {
116700
+ return;
116701
+ }
116702
+ auto state = (CAPITaskState *)state_p;
116703
+ *state->marker = false;
116704
+ if (state->execute_count > 0) {
116705
+ // signal to the threads to wake up
116706
+ auto &scheduler = duckdb::TaskScheduler::GetScheduler(state->db);
116707
+ scheduler.Signal(state->execute_count);
116708
+ }
116709
+ }
116710
+
116711
+ void duckdb_destroy_task_state(duckdb_task_state state_p) {
116712
+ if (!state_p) {
116713
+ return;
116714
+ }
116715
+ auto state = (CAPITaskState *)state_p;
116716
+ delete state;
116717
+ }
116718
+
116666
116719
 
116667
116720
 
116668
116721
 
@@ -149324,7 +149377,7 @@ void TaskScheduler::ExecuteForever(atomic<bool> *marker) {
149324
149377
  unique_ptr<Task> task;
149325
149378
  // loop until the marker is set to false
149326
149379
  while (*marker) {
149327
- // wait for a signal with a timeout; the timeout allows us to periodically check
149380
+ // wait for a signal with a timeout
149328
149381
  queue->semaphore.wait();
149329
149382
  if (queue->q.try_dequeue(task)) {
149330
149383
  task->Execute(TaskExecutionMode::PROCESS_ALL);
@@ -149380,6 +149433,12 @@ void TaskScheduler::SetThreads(int32_t n) {
149380
149433
  #endif
149381
149434
  }
149382
149435
 
149436
+ void TaskScheduler::Signal(idx_t n) {
149437
+ #ifndef DUCKDB_NO_THREADS
149438
+ queue->semaphore.signal(n);
149439
+ #endif
149440
+ }
149441
+
149383
149442
  void TaskScheduler::SetThreadsInternal(int32_t n) {
149384
149443
  #ifndef DUCKDB_NO_THREADS
149385
149444
  if (threads.size() == idx_t(n - 1)) {
@@ -149391,7 +149450,7 @@ void TaskScheduler::SetThreadsInternal(int32_t n) {
149391
149450
  for (idx_t i = 0; i < threads.size(); i++) {
149392
149451
  *markers[i] = false;
149393
149452
  }
149394
- queue->semaphore.signal(threads.size());
149453
+ Signal(threads.size());
149395
149454
  // now join the threads to ensure they are fully stopped before erasing them
149396
149455
  for (idx_t i = 0; i < threads.size(); i++) {
149397
149456
  threads[i]->internal_thread->join();
package/src/duckdb.hpp CHANGED
@@ -11,8 +11,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
11
11
  #pragma once
12
12
  #define DUCKDB_AMALGAMATION 1
13
13
  #define DUCKDB_AMALGAMATION_EXTENDED 1
14
- #define DUCKDB_SOURCE_ID "6937493e4"
15
- #define DUCKDB_VERSION "v0.4.1-dev1016"
14
+ #define DUCKDB_SOURCE_ID "4aa7d9569"
15
+ #define DUCKDB_VERSION "v0.4.1-dev1022"
16
16
  //===----------------------------------------------------------------------===//
17
17
  // DuckDB
18
18
  //
@@ -11189,6 +11189,9 @@ public:
11189
11189
  //! Returns the number of threads
11190
11190
  int32_t NumberOfThreads();
11191
11191
 
11192
+ //! Send signals to n threads, signalling for them to wake up and attempt to execute a task
11193
+ void Signal(idx_t n);
11194
+
11192
11195
  private:
11193
11196
  void SetThreadsInternal(int32_t n);
11194
11197
 
@@ -17761,6 +17764,8 @@ DUCKDB_API void duckdb_destroy_arrow(duckdb_arrow *result);
17761
17764
  //===--------------------------------------------------------------------===//
17762
17765
  // Threading Information
17763
17766
  //===--------------------------------------------------------------------===//
17767
+ typedef void *duckdb_task_state;
17768
+
17764
17769
  /*!
17765
17770
  Execute DuckDB tasks on this thread.
17766
17771
 
@@ -17771,6 +17776,44 @@ Will return after `max_tasks` have been executed, or if there are no more tasks
17771
17776
  */
17772
17777
  DUCKDB_API void duckdb_execute_tasks(duckdb_database database, idx_t max_tasks);
17773
17778
 
17779
+ /*!
17780
+ Creates a task state that can be used with duckdb_execute_tasks_state to execute tasks until
17781
+ duckdb_finish_execution is called on the state.
17782
+
17783
+ duckdb_destroy_state should be called on the result in order to free memory.
17784
+
17785
+ * database: The database object to create the task state for
17786
+ * returns: The task state that can be used with duckdb_execute_tasks_state.
17787
+ */
17788
+ DUCKDB_API duckdb_task_state duckdb_create_task_state(duckdb_database database);
17789
+
17790
+ /*!
17791
+ Execute DuckDB tasks on this thread.
17792
+
17793
+ The thread will keep on executing tasks forever, until duckdb_finish_execution is called on the state.
17794
+ Multiple threads can share the same duckdb_task_state.
17795
+
17796
+ * state: The task state of the executor
17797
+ */
17798
+ DUCKDB_API void duckdb_execute_tasks_state(duckdb_task_state state);
17799
+
17800
+ /*!
17801
+ Finish execution on a specific task.
17802
+
17803
+ * state: The task state to finish execution
17804
+ */
17805
+ DUCKDB_API void duckdb_finish_execution(duckdb_task_state state);
17806
+
17807
+ /*!
17808
+ Destroys the task state returned from duckdb_create_task_state.
17809
+
17810
+ Note that this should not be called while there is an active duckdb_execute_tasks_state running
17811
+ on the task state.
17812
+
17813
+ * state: The task state to clean up
17814
+ */
17815
+ DUCKDB_API void duckdb_destroy_task_state(duckdb_task_state state);
17816
+
17774
17817
  #ifdef __cplusplus
17775
17818
  }
17776
17819
  #endif