duckdb 0.3.1-dev11.0 → 0.3.1-dev210.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 +17026 -14141
  3. package/src/duckdb.hpp +303 -183
package/src/duckdb.hpp CHANGED
@@ -10,8 +10,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
10
10
 
11
11
  #pragma once
12
12
  #define DUCKDB_AMALGAMATION 1
13
- #define DUCKDB_SOURCE_ID "42decfe98"
14
- #define DUCKDB_VERSION "0.3.1-dev11"
13
+ #define DUCKDB_SOURCE_ID "f05f6f50f"
14
+ #define DUCKDB_VERSION "0.3.1-dev210"
15
15
  //===----------------------------------------------------------------------===//
16
16
  // DuckDB
17
17
  //
@@ -567,11 +567,12 @@ using std::vector;
567
567
  #endif
568
568
 
569
569
 
570
+
570
571
  namespace duckdb {
571
572
 
572
573
  class Serializer;
573
574
  class Deserializer;
574
-
575
+ class Value;
575
576
  //! Type used to represent dates (days since 1970-01-01)
576
577
  struct date_t {
577
578
  int32_t days;
@@ -861,12 +862,12 @@ enum class PhysicalType : uint8_t {
861
862
  /// Like LIST, but with 64-bit offsets
862
863
  LARGE_LIST = 33,
863
864
 
864
- // DuckDB Extensions
865
+ /// DuckDB Extensions
865
866
  VARCHAR = 200, // our own string representation, different from STRING and LARGE_STRING above
866
867
  INT128 = 204, // 128-bit integers
867
-
868
+ UNKNOWN = 205, // Unknown physical type of user defined types
868
869
  /// Boolean as 1 bit, LSB bit-packed ordering
869
- BIT = 205,
870
+ BIT = 206,
870
871
 
871
872
  INVALID = 255
872
873
  };
@@ -879,7 +880,7 @@ enum class LogicalTypeId : uint8_t {
879
880
  SQLNULL = 1, /* NULL type, used for constant NULL */
880
881
  UNKNOWN = 2, /* unknown type, used for parameter expressions */
881
882
  ANY = 3, /* ANY type, used for functions that accept any type as parameter */
882
-
883
+ USER = 4, /* A User Defined Type (e.g., ENUMs before the binder) */
883
884
  BOOLEAN = 10,
884
885
  TINYINT = 11,
885
886
  SMALLINT = 12,
@@ -913,7 +914,8 @@ enum class LogicalTypeId : uint8_t {
913
914
  STRUCT = 100,
914
915
  LIST = 101,
915
916
  MAP = 102,
916
- TABLE = 103
917
+ TABLE = 103,
918
+ ENUM = 104
917
919
  };
918
920
 
919
921
  struct ExtraTypeInfo;
@@ -922,6 +924,7 @@ struct LogicalType {
922
924
  DUCKDB_API LogicalType();
923
925
  DUCKDB_API LogicalType(LogicalTypeId id); // NOLINT: Allow implicit conversion from `LogicalTypeId`
924
926
  DUCKDB_API LogicalType(LogicalTypeId id, shared_ptr<ExtraTypeInfo> type_info);
927
+
925
928
  DUCKDB_API LogicalType(const LogicalType &other) :
926
929
  id_(other.id_), physical_type_(other.physical_type_), type_info_(other.type_info_) {}
927
930
 
@@ -1018,10 +1021,11 @@ public:
1018
1021
  // explicitly allowing these functions to be capitalized to be in-line with the remaining functions
1019
1022
  DUCKDB_API static LogicalType DECIMAL(int width, int scale); // NOLINT
1020
1023
  DUCKDB_API static LogicalType VARCHAR_COLLATION(string collation); // NOLINT
1021
- DUCKDB_API static LogicalType LIST(LogicalType child); // NOLINT
1022
- DUCKDB_API static LogicalType STRUCT(child_list_t<LogicalType> children); // NOLINT
1023
- DUCKDB_API static LogicalType MAP(child_list_t<LogicalType> children); // NOLINT
1024
-
1024
+ DUCKDB_API static LogicalType LIST( LogicalType child); // NOLINT
1025
+ DUCKDB_API static LogicalType STRUCT( child_list_t<LogicalType> children); // NOLINT
1026
+ DUCKDB_API static LogicalType MAP( child_list_t<LogicalType> children); // NOLINT
1027
+ DUCKDB_API static LogicalType ENUM(const string &enum_name, const vector<string> &ordered_data); // NOLINT
1028
+ DUCKDB_API static LogicalType USER(const string &user_type_name); // NOLINT
1025
1029
  //! A list of all NUMERIC types (integral and floating point types)
1026
1030
  DUCKDB_API static const vector<LogicalType> NUMERIC;
1027
1031
  //! A list of all INTEGRAL types
@@ -1043,6 +1047,18 @@ struct ListType {
1043
1047
  DUCKDB_API static const LogicalType &GetChildType(const LogicalType &type);
1044
1048
  };
1045
1049
 
1050
+ struct UserType{
1051
+ DUCKDB_API static const string &GetTypeName(const LogicalType &type);
1052
+ };
1053
+
1054
+ struct EnumType{
1055
+ DUCKDB_API static const string &GetTypeName(const LogicalType &type);
1056
+ DUCKDB_API static int64_t GetPos(const LogicalType &type, const string& key);
1057
+ DUCKDB_API static const vector<string> &GetValuesInsertOrder(const LogicalType &type);
1058
+ DUCKDB_API static idx_t GetSize(const LogicalType &type);
1059
+ DUCKDB_API static const string& GetValue(const Value &val);
1060
+ };
1061
+
1046
1062
  struct StructType {
1047
1063
  DUCKDB_API static const child_list_t<LogicalType> &GetChildTypes(const LogicalType &type);
1048
1064
  DUCKDB_API static const LogicalType &GetChildType(const LogicalType &type, idx_t index);
@@ -1497,7 +1513,7 @@ public:
1497
1513
  //! Write a string with a length prefix
1498
1514
  void WriteString(const string &val) {
1499
1515
  Write<uint32_t>((uint32_t)val.size());
1500
- if (val.size() > 0) {
1516
+ if (!val.empty()) {
1501
1517
  WriteData((const_data_ptr_t)val.c_str(), val.size());
1502
1518
  }
1503
1519
  }
@@ -2568,6 +2584,9 @@ public:
2568
2584
  DUCKDB_API static Value INTERVAL(int32_t months, int32_t days, int64_t micros);
2569
2585
  DUCKDB_API static Value INTERVAL(interval_t interval);
2570
2586
 
2587
+ // Create a enum Value from a specified uint value
2588
+ DUCKDB_API static Value ENUM(uint64_t value, const LogicalType &original_type);
2589
+
2571
2590
  // Decimal values
2572
2591
  DUCKDB_API static Value DECIMAL(int16_t value, uint8_t width, uint8_t scale);
2573
2592
  DUCKDB_API static Value DECIMAL(int32_t value, uint8_t width, uint8_t scale);
@@ -3293,6 +3312,9 @@ public:
3293
3312
  //! Without changing the type of this vector
3294
3313
  void Reinterpret(Vector &other);
3295
3314
 
3315
+ //! Causes this vector to reference the data held by the other vector, changes the type if required.
3316
+ void ReferenceAndSetType(Vector &other);
3317
+
3296
3318
  //! Resets a vector from a vector cache.
3297
3319
  //! This turns the vector back into an empty FlatVector with STANDARD_VECTOR_SIZE entries.
3298
3320
  //! The VectorCache is used so this can be done without requiring any allocations.
@@ -7134,6 +7156,7 @@ enum class CatalogType : uint8_t {
7134
7156
  PREPARED_STATEMENT = 5,
7135
7157
  SEQUENCE_ENTRY = 6,
7136
7158
  COLLATION_ENTRY = 7,
7159
+ TYPE_ENTRY = 8,
7137
7160
 
7138
7161
  // functions
7139
7162
  TABLE_FUNCTION_ENTRY = 25,
@@ -7302,6 +7325,7 @@ struct CreateFunctionInfo;
7302
7325
  struct CreateViewInfo;
7303
7326
  struct CreateSequenceInfo;
7304
7327
  struct CreateCollationInfo;
7328
+ struct CreateTypeInfo;
7305
7329
 
7306
7330
  class ClientContext;
7307
7331
  class Transaction;
@@ -7390,6 +7414,8 @@ public:
7390
7414
  CatalogEntry *CreateView(ClientContext &context, CreateViewInfo *info);
7391
7415
  //! Creates a table in the catalog.
7392
7416
  CatalogEntry *CreateSequence(ClientContext &context, CreateSequenceInfo *info);
7417
+ //! Creates a Enum in the catalog.
7418
+ CatalogEntry *CreateType(ClientContext &context, CreateTypeInfo *info);
7393
7419
  //! Creates a collation in the catalog
7394
7420
  CatalogEntry *CreateCollation(ClientContext &context, CreateCollationInfo *info);
7395
7421
 
@@ -7409,6 +7435,8 @@ public:
7409
7435
  CatalogEntry *CreateView(ClientContext &context, SchemaCatalogEntry *schema, CreateViewInfo *info);
7410
7436
  //! Creates a table in the catalog.
7411
7437
  CatalogEntry *CreateSequence(ClientContext &context, SchemaCatalogEntry *schema, CreateSequenceInfo *info);
7438
+ //! Creates a enum in the catalog.
7439
+ CatalogEntry *CreateType(ClientContext &context, SchemaCatalogEntry *schema, CreateTypeInfo *info);
7412
7440
  //! Creates a collation in the catalog
7413
7441
  CatalogEntry *CreateCollation(ClientContext &context, SchemaCatalogEntry *schema, CreateCollationInfo *info);
7414
7442
 
@@ -7555,6 +7583,7 @@ enum class LogicalOperatorType : uint8_t {
7555
7583
  LOGICAL_DROP = 132,
7556
7584
  LOGICAL_PRAGMA = 133,
7557
7585
  LOGICAL_TRANSACTION = 134,
7586
+ LOGICAL_CREATE_TYPE = 135,
7558
7587
 
7559
7588
  // -----------------------------
7560
7589
  // Explain
@@ -9249,7 +9278,7 @@ public:
9249
9278
  //! Delete from a table, can only be used on a TableRelation
9250
9279
  DUCKDB_API virtual void Delete(const string &condition = string());
9251
9280
  //! Create a relation from calling a table in/out function on the input relation
9252
- DUCKDB_API shared_ptr<Relation> TableFunction(const std::string &fname, vector<Value> values);
9281
+ DUCKDB_API shared_ptr<Relation> TableFunction(const std::string &fname, const vector<Value> &values);
9253
9282
 
9254
9283
  public:
9255
9284
  //! Whether or not the relation inherits column bindings from its child or not, only relevant for binding
@@ -9504,7 +9533,7 @@ public:
9504
9533
  DUCKDB_API shared_ptr<Relation> ReadCSV(const string &csv_file);
9505
9534
  DUCKDB_API shared_ptr<Relation> ReadCSV(const string &csv_file, const vector<string> &columns);
9506
9535
  //! Returns a relation from a query
9507
- DUCKDB_API shared_ptr<Relation> RelationFromQuery(string query, string alias = "queryrelation");
9536
+ DUCKDB_API shared_ptr<Relation> RelationFromQuery(const string &query, const string &alias = "queryrelation");
9508
9537
 
9509
9538
  DUCKDB_API void BeginTransaction();
9510
9539
  DUCKDB_API void Commit();
@@ -12138,6 +12167,7 @@ struct CreateSequenceInfo;
12138
12167
  struct CreateSchemaInfo;
12139
12168
  struct CreateTableFunctionInfo;
12140
12169
  struct CreateCopyFunctionInfo;
12170
+ struct CreateTypeInfo;
12141
12171
 
12142
12172
  struct DropInfo;
12143
12173
 
@@ -12165,6 +12195,8 @@ private:
12165
12195
  CatalogSet sequences;
12166
12196
  //! The catalog set holding the collations
12167
12197
  CatalogSet collations;
12198
+ //! The catalog set holding the types
12199
+ CatalogSet types;
12168
12200
 
12169
12201
  public:
12170
12202
  //! Scan the specified catalog set, invoking the callback method for every entry
@@ -12199,6 +12231,8 @@ private:
12199
12231
  CatalogEntry *CreatePragmaFunction(ClientContext &context, CreatePragmaFunctionInfo *info);
12200
12232
  //! Create a collation within the given schema
12201
12233
  CatalogEntry *CreateCollation(ClientContext &context, CreateCollationInfo *info);
12234
+ //! Create a enum within the given schema
12235
+ CatalogEntry *CreateType(ClientContext &context, CreateTypeInfo *info);
12202
12236
 
12203
12237
  //! Drops an entry from the schema
12204
12238
  void DropEntry(ClientContext &context, DropInfo *info);
@@ -12307,16 +12341,6 @@ using std::thread;
12307
12341
 
12308
12342
 
12309
12343
 
12310
- //===----------------------------------------------------------------------===//
12311
- // DuckDB
12312
- //
12313
- // duckdb/execution/physical_sink.hpp
12314
- //
12315
- //
12316
- //===----------------------------------------------------------------------===//
12317
-
12318
-
12319
-
12320
12344
  //===----------------------------------------------------------------------===//
12321
12345
  // DuckDB
12322
12346
  //
@@ -12407,6 +12431,7 @@ enum class PhysicalOperatorType : uint8_t {
12407
12431
  DROP,
12408
12432
  PRAGMA,
12409
12433
  TRANSACTION,
12434
+ CREATE_TYPE,
12410
12435
 
12411
12436
  // -----------------------------
12412
12437
  // Helpers
@@ -12442,60 +12467,110 @@ string PhysicalOperatorToString(PhysicalOperatorType type);
12442
12467
  namespace duckdb {
12443
12468
  class ClientContext;
12444
12469
  class ThreadContext;
12445
- class TaskContext;
12446
12470
 
12447
12471
  class ExecutionContext {
12448
12472
  public:
12449
- ExecutionContext(ClientContext &client_p, ThreadContext &thread_p, TaskContext &task_p)
12450
- : client(client_p), thread(thread_p), task(task_p) {
12473
+ ExecutionContext(ClientContext &client_p, ThreadContext &thread_p) : client(client_p), thread(thread_p) {
12451
12474
  }
12452
12475
 
12453
12476
  //! The client-global context; caution needs to be taken when used in parallel situations
12454
12477
  ClientContext &client;
12455
12478
  //! The thread-local context for this execution
12456
12479
  ThreadContext &thread;
12457
- //! The task context for this execution
12458
- TaskContext &task;
12459
12480
  };
12460
12481
 
12461
12482
  } // namespace duckdb
12462
12483
 
12484
+ //===----------------------------------------------------------------------===//
12485
+ // DuckDB
12486
+ //
12487
+ // duckdb/common/enums/operator_result_type.hpp
12488
+ //
12489
+ //
12490
+ //===----------------------------------------------------------------------===//
12491
+
12492
+
12463
12493
 
12464
12494
 
12465
- #include <functional>
12466
- #include <utility>
12467
12495
 
12468
12496
  namespace duckdb {
12469
- class ExpressionExecutor;
12497
+
12498
+ //! The OperatorResultType is used to indicate how data should flow around a regular (i.e. non-sink and non-source)
12499
+ //! physical operator
12500
+ //! There are three possible results:
12501
+ //! NEED_MORE_INPUT means the operator is done with the current input and can consume more input if available
12502
+ //! If there is more input the operator will be called with more input, otherwise the operator will not be called again.
12503
+ //! HAVE_MORE_OUTPUT means the operator is not finished yet with the current input.
12504
+ //! The operator will be called again with the same input.
12505
+ //! FINISHED means the operator has finished the entire pipeline and no more processing is necessary.
12506
+ //! The operator will not be called again, and neither will any other operators in this pipeline.
12507
+ enum class OperatorResultType : uint8_t { NEED_MORE_INPUT, HAVE_MORE_OUTPUT, FINISHED };
12508
+
12509
+ //! The SinkResultType is used to indicate the result of data flowing into a sink
12510
+ //! There are two possible results:
12511
+ //! NEED_MORE_INPUT means the sink needs more input
12512
+ //! FINISHED means the sink is finished executing, and more input will not change the result any further
12513
+ enum class SinkResultType : uint8_t { NEED_MORE_INPUT, FINISHED };
12514
+
12515
+ //! The SinkFinalizeType is used to indicate the result of a Finalize call on a sink
12516
+ //! There are two possible results:
12517
+ //! READY means the sink is ready for further processing
12518
+ //! NO_OUTPUT_POSSIBLE means the sink will never provide output, and any pipelines involving the sink can be skipped
12519
+ enum class SinkFinalizeType : uint8_t { READY, NO_OUTPUT_POSSIBLE };
12520
+
12521
+ } // namespace duckdb
12522
+
12523
+
12524
+ namespace duckdb {
12525
+ class Event;
12470
12526
  class PhysicalOperator;
12527
+ class Pipeline;
12528
+
12529
+ // LCOV_EXCL_START
12530
+ class OperatorState {
12531
+ public:
12532
+ virtual ~OperatorState() {
12533
+ }
12471
12534
 
12472
- //! The current state/context of the operator. The PhysicalOperatorState is
12473
- //! updated using the GetChunk function, and allows the caller to repeatedly
12474
- //! call the GetChunk function and get new batches of data everytime until the
12475
- //! data source is exhausted.
12476
- class PhysicalOperatorState {
12535
+ virtual void Finalize(PhysicalOperator *op, ExecutionContext &context) {
12536
+ }
12537
+ };
12538
+
12539
+ class GlobalSinkState {
12477
12540
  public:
12478
- PhysicalOperatorState(PhysicalOperator &op, PhysicalOperator *child);
12479
- virtual ~PhysicalOperatorState() = default;
12541
+ GlobalSinkState() : state(SinkFinalizeType::READY) {
12542
+ }
12543
+ virtual ~GlobalSinkState() {
12544
+ }
12480
12545
 
12481
- //! Flag indicating whether or not the operator is finished [note: not all
12482
- //! operators use this flag]
12483
- bool finished;
12484
- //! DataChunk that stores data from the child of this operator
12485
- DataChunk child_chunk;
12486
- //! State of the child of this operator
12487
- unique_ptr<PhysicalOperatorState> child_state;
12546
+ SinkFinalizeType state;
12488
12547
  };
12489
12548
 
12549
+ class LocalSinkState {
12550
+ public:
12551
+ virtual ~LocalSinkState() {
12552
+ }
12553
+ };
12554
+
12555
+ class GlobalSourceState {
12556
+ public:
12557
+ virtual ~GlobalSourceState() {
12558
+ }
12559
+
12560
+ virtual idx_t MaxThreads() {
12561
+ return 1;
12562
+ }
12563
+ };
12564
+
12565
+ class LocalSourceState {
12566
+ public:
12567
+ virtual ~LocalSourceState() {
12568
+ }
12569
+ };
12570
+ // LCOV_EXCL_STOP
12571
+
12490
12572
  //! PhysicalOperator is the base class of the physical operators present in the
12491
12573
  //! execution plan
12492
- /*!
12493
- The execution model is a pull-based execution model. GetChunk is called on
12494
- the root node, which causes the root node to be executed, and presumably call
12495
- GetChunk again on its child nodes. Every node in the operator chain has a
12496
- state that is updated as GetChunk is called: PhysicalOperatorState (different
12497
- operators subclass this state and add different properties).
12498
- */
12499
12574
  class PhysicalOperator {
12500
12575
  public:
12501
12576
  PhysicalOperator(PhysicalOperatorType type, vector<LogicalType> types, idx_t estimated_cardinality)
@@ -12512,6 +12587,8 @@ public:
12512
12587
  vector<LogicalType> types;
12513
12588
  //! The extimated cardinality of this physical operator
12514
12589
  idx_t estimated_cardinality;
12590
+ //! The global sink state of this operator
12591
+ unique_ptr<GlobalSinkState> sink_state;
12515
12592
 
12516
12593
  public:
12517
12594
  virtual string GetName() const;
@@ -12519,97 +12596,78 @@ public:
12519
12596
  return "";
12520
12597
  }
12521
12598
  virtual string ToString() const;
12522
- void Print();
12599
+ void Print() const;
12523
12600
 
12524
12601
  //! Return a vector of the types that will be returned by this operator
12525
- vector<LogicalType> &GetTypes() {
12602
+ const vector<LogicalType> &GetTypes() const {
12526
12603
  return types;
12527
12604
  }
12528
- //! Initialize a given chunk to the types that will be returned by this
12529
- //! operator, this will prepare chunk for a call to GetChunk. This method
12530
- //! only has to be called once for any amount of calls to GetChunk.
12531
- virtual void InitializeChunk(DataChunk &chunk) {
12532
- auto &types = GetTypes();
12533
- chunk.Initialize(types);
12534
- }
12535
- //! Retrieves a chunk from this operator and stores it in the chunk
12536
- //! variable.
12537
- virtual void GetChunkInternal(ExecutionContext &context, DataChunk &chunk, PhysicalOperatorState *state) const = 0;
12538
12605
 
12539
- void GetChunk(ExecutionContext &context, DataChunk &chunk, PhysicalOperatorState *state) const;
12540
-
12541
- //! Create a new empty instance of the operator state
12542
- virtual unique_ptr<PhysicalOperatorState> GetOperatorState() {
12543
- return make_unique<PhysicalOperatorState>(*this, children.size() == 0 ? nullptr : children[0].get());
12606
+ virtual bool Equals(const PhysicalOperator &other) const {
12607
+ return false;
12544
12608
  }
12545
12609
 
12546
- virtual void FinalizeOperatorState(PhysicalOperatorState &state, ExecutionContext &context) {
12547
- if (!children.empty() && state.child_state) {
12548
- children[0]->FinalizeOperatorState(*state.child_state, context);
12549
- }
12550
- }
12610
+ public:
12611
+ // Operator interface
12612
+ virtual unique_ptr<OperatorState> GetOperatorState(ClientContext &context) const;
12613
+ virtual OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk,
12614
+ OperatorState &state) const;
12551
12615
 
12552
- virtual bool IsSink() const {
12616
+ virtual bool ParallelOperator() const {
12553
12617
  return false;
12554
12618
  }
12555
- };
12556
-
12557
- } // namespace duckdb
12558
12619
 
12559
-
12560
- namespace duckdb {
12561
-
12562
- class Pipeline;
12563
-
12564
- class GlobalOperatorState {
12565
- public:
12566
- virtual ~GlobalOperatorState() {
12620
+ virtual bool RequiresCache() const {
12621
+ return false;
12567
12622
  }
12568
- };
12569
12623
 
12570
- class LocalSinkState {
12571
12624
  public:
12572
- virtual ~LocalSinkState() {
12573
- }
12574
- };
12625
+ // Source interface
12626
+ virtual unique_ptr<LocalSourceState> GetLocalSourceState(ExecutionContext &context,
12627
+ GlobalSourceState &gstate) const;
12628
+ virtual unique_ptr<GlobalSourceState> GetGlobalSourceState(ClientContext &context) const;
12629
+ virtual void GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate,
12630
+ LocalSourceState &lstate) const;
12575
12631
 
12576
- class PhysicalSink : public PhysicalOperator {
12577
- public:
12578
- PhysicalSink(PhysicalOperatorType type, vector<LogicalType> types, idx_t estimated_cardinality)
12579
- : PhysicalOperator(type, move(types), estimated_cardinality) {
12632
+ virtual bool IsSource() const {
12633
+ return false;
12580
12634
  }
12581
12635
 
12582
- unique_ptr<GlobalOperatorState> sink_state;
12636
+ virtual bool ParallelSource() const {
12637
+ return false;
12638
+ }
12583
12639
 
12584
12640
  public:
12641
+ // Sink interface
12642
+
12585
12643
  //! The sink method is called constantly with new input, as long as new input is available. Note that this method
12586
- //! CAN be called in parallel, proper locking is needed when accessing data inside the GlobalOperatorState.
12587
- virtual void Sink(ExecutionContext &context, GlobalOperatorState &gstate, LocalSinkState &lstate,
12588
- DataChunk &input) const = 0;
12644
+ //! CAN be called in parallel, proper locking is needed when accessing data inside the GlobalSinkState.
12645
+ virtual SinkResultType Sink(ExecutionContext &context, GlobalSinkState &gstate, LocalSinkState &lstate,
12646
+ DataChunk &input) const;
12589
12647
  // The combine is called when a single thread has completed execution of its part of the pipeline, it is the final
12590
12648
  // time that a specific LocalSinkState is accessible. This method can be called in parallel while other Sink() or
12591
- // Combine() calls are active on the same GlobalOperatorState.
12592
- virtual void Combine(ExecutionContext &context, GlobalOperatorState &gstate, LocalSinkState &lstate) {
12593
- }
12649
+ // Combine() calls are active on the same GlobalSinkState.
12650
+ virtual void Combine(ExecutionContext &context, GlobalSinkState &gstate, LocalSinkState &lstate) const;
12594
12651
  //! The finalize is called when ALL threads are finished execution. It is called only once per pipeline, and is
12595
12652
  //! entirely single threaded.
12596
- virtual bool Finalize(Pipeline &pipeline, ClientContext &context, unique_ptr<GlobalOperatorState> gstate) {
12597
- this->sink_state = move(gstate);
12598
- return true;
12599
- }
12653
+ //! If Finalize returns SinkResultType::FINISHED, the sink is marked as finished
12654
+ virtual SinkFinalizeType Finalize(Pipeline &pipeline, Event &event, ClientContext &context,
12655
+ GlobalSinkState &gstate) const;
12600
12656
 
12601
- virtual unique_ptr<LocalSinkState> GetLocalSinkState(ExecutionContext &context) {
12602
- return make_unique<LocalSinkState>();
12603
- }
12604
- virtual unique_ptr<GlobalOperatorState> GetGlobalState(ClientContext &context) {
12605
- return make_unique<GlobalOperatorState>();
12657
+ virtual unique_ptr<LocalSinkState> GetLocalSinkState(ExecutionContext &context) const;
12658
+ virtual unique_ptr<GlobalSinkState> GetGlobalSinkState(ClientContext &context) const;
12659
+
12660
+ virtual bool IsSink() const {
12661
+ return false;
12606
12662
  }
12607
12663
 
12608
- bool IsSink() const override {
12609
- return true;
12664
+ virtual bool ParallelSink() const {
12665
+ return false;
12610
12666
  }
12611
12667
 
12612
- void Schedule(ClientContext &context);
12668
+ virtual bool SinkOrderMatters() const {
12669
+ return false;
12670
+ }
12613
12671
  };
12614
12672
 
12615
12673
  } // namespace duckdb
@@ -12668,7 +12726,9 @@ typedef void (*table_function_cleanup_t)(ClientContext &context, const FunctionD
12668
12726
  FunctionOperatorData *operator_state);
12669
12727
  typedef idx_t (*table_function_max_threads_t)(ClientContext &context, const FunctionData *bind_data);
12670
12728
  typedef unique_ptr<ParallelState> (*table_function_init_parallel_state_t)(ClientContext &context,
12671
- const FunctionData *bind_data);
12729
+ const FunctionData *bind_data,
12730
+ const vector<column_t> &column_ids,
12731
+ TableFilterCollection *filters);
12672
12732
  typedef unique_ptr<FunctionOperatorData> (*table_function_init_parallel_t)(ClientContext &context,
12673
12733
  const FunctionData *bind_data,
12674
12734
  ParallelState *state,
@@ -12820,7 +12880,10 @@ struct ParallelState {
12820
12880
 
12821
12881
 
12822
12882
  namespace duckdb {
12883
+ class ClientContext;
12884
+ class Executor;
12823
12885
 
12886
+ //! Generic parallel task
12824
12887
  class Task {
12825
12888
  public:
12826
12889
  virtual ~Task() {
@@ -12830,6 +12893,21 @@ public:
12830
12893
  virtual void Execute() = 0;
12831
12894
  };
12832
12895
 
12896
+ //! Execute a task within an executor, including exception handling
12897
+ //! This should be used within queries
12898
+ class ExecutorTask : public Task {
12899
+ public:
12900
+ ExecutorTask(Executor &executor);
12901
+ ExecutorTask(ClientContext &context);
12902
+ virtual ~ExecutorTask();
12903
+
12904
+ Executor &executor;
12905
+
12906
+ public:
12907
+ virtual void ExecuteTask() = 0;
12908
+ void Execute() override;
12909
+ };
12910
+
12833
12911
  } // namespace duckdb
12834
12912
 
12835
12913
 
@@ -12894,109 +12972,87 @@ private:
12894
12972
 
12895
12973
  namespace duckdb {
12896
12974
  class Executor;
12897
- class TaskContext;
12975
+ class Event;
12898
12976
 
12899
12977
  //! The Pipeline class represents an execution pipeline
12900
12978
  class Pipeline : public std::enable_shared_from_this<Pipeline> {
12901
12979
  friend class Executor;
12980
+ friend class PipelineExecutor;
12981
+ friend class PipelineEvent;
12982
+ friend class PipelineFinishEvent;
12902
12983
 
12903
12984
  public:
12904
- Pipeline(Executor &execution_context, ProducerToken &token);
12985
+ Pipeline(Executor &execution_context);
12905
12986
 
12906
12987
  Executor &executor;
12907
- ProducerToken &token;
12908
12988
 
12909
12989
  public:
12910
- //! Execute a task within the pipeline on a single thread
12911
- void Execute(TaskContext &task);
12990
+ ClientContext &GetClientContext();
12912
12991
 
12913
12992
  void AddDependency(shared_ptr<Pipeline> &pipeline);
12914
- void CompleteDependency();
12915
- bool HasDependencies() {
12916
- return !dependencies.empty();
12917
- }
12918
12993
 
12919
- void Reset(ClientContext &context);
12920
- void Schedule();
12994
+ void Ready();
12995
+ void Reset();
12996
+ void ResetSource();
12997
+ void Schedule(shared_ptr<Event> &event);
12921
12998
 
12922
- //! Finish a single task of this pipeline
12923
- void FinishTask();
12924
- //! Finish executing this pipeline
12925
- void Finish();
12999
+ //! Finalize this pipeline
13000
+ void Finalize(Event &event);
12926
13001
 
12927
13002
  string ToString() const;
12928
13003
  void Print() const;
12929
13004
 
12930
- void SetRecursiveCTE(PhysicalOperator *op) {
12931
- this->recursive_cte = op;
12932
- }
12933
- PhysicalOperator *GetRecursiveCTE() {
12934
- return recursive_cte;
12935
- }
12936
- void ClearParents();
12937
-
12938
- void IncrementTasks(idx_t amount) {
12939
- this->total_tasks += amount;
12940
- }
12941
-
12942
- bool IsFinished() {
12943
- return finished;
12944
- }
12945
13005
  //! Returns query progress
12946
13006
  bool GetProgress(int &current_percentage);
12947
13007
 
12948
- public:
12949
- //! The current threads working on the pipeline
12950
- atomic<idx_t> finished_tasks;
12951
- //! The maximum amount of threads that can work on the pipeline
12952
- atomic<idx_t> total_tasks;
13008
+ //! Returns a list of all operators (including source and sink) involved in this pipeline
13009
+ vector<PhysicalOperator *> GetOperators() const;
13010
+
13011
+ PhysicalOperator *GetSink() {
13012
+ return sink;
13013
+ }
12953
13014
 
12954
13015
  private:
12955
- //! The child from which to pull chunks
12956
- PhysicalOperator *child;
12957
- //! The global sink state
12958
- unique_ptr<GlobalOperatorState> sink_state;
13016
+ //! Whether or not the pipeline has been readied
13017
+ bool ready;
13018
+ //! The source of this pipeline
13019
+ PhysicalOperator *source;
13020
+ //! The chain of intermediate operators
13021
+ vector<PhysicalOperator *> operators;
12959
13022
  //! The sink (i.e. destination) for data; this is e.g. a hash table to-be-built
12960
- PhysicalSink *sink;
13023
+ PhysicalOperator *sink;
13024
+
13025
+ //! The global source state
13026
+ unique_ptr<GlobalSourceState> source_state;
13027
+
12961
13028
  //! The parent pipelines (i.e. pipelines that are dependent on this pipeline to finish)
12962
- unordered_map<Pipeline *, weak_ptr<Pipeline>> parents;
13029
+ vector<weak_ptr<Pipeline>> parents;
12963
13030
  //! The dependencies of this pipeline
12964
- unordered_map<Pipeline *, weak_ptr<Pipeline>> dependencies;
12965
- //! The amount of completed dependencies (the pipeline can only be started after the dependencies have finished
12966
- //! executing)
12967
- atomic<idx_t> finished_dependencies;
12968
-
12969
- //! The parallel operator (if any)
12970
- PhysicalOperator *parallel_node;
12971
- //! The parallel state (if any)
12972
- unique_ptr<ParallelState> parallel_state;
12973
-
12974
- //! Whether or not the pipeline is finished executing
12975
- bool finished;
12976
- //! The recursive CTE node that this pipeline belongs to, and may be executed multiple times
12977
- PhysicalOperator *recursive_cte;
13031
+ vector<weak_ptr<Pipeline>> dependencies;
12978
13032
 
12979
13033
  private:
12980
- bool GetProgress(ClientContext &context, PhysicalOperator *op, int &current_percentage);
12981
- void ScheduleSequentialTask();
12982
- bool LaunchScanTasks(PhysicalOperator *op, idx_t max_threads, unique_ptr<ParallelState> parallel_state);
12983
- bool ScheduleOperator(PhysicalOperator *op);
13034
+ bool GetProgressInternal(ClientContext &context, PhysicalOperator *op, int &current_percentage);
13035
+ void ScheduleSequentialTask(shared_ptr<Event> &event);
13036
+ bool LaunchScanTasks(shared_ptr<Event> &event, idx_t max_threads);
13037
+
13038
+ bool ScheduleParallel(shared_ptr<Event> &event);
12984
13039
  };
12985
13040
 
12986
13041
  } // namespace duckdb
12987
13042
 
12988
13043
 
12989
13044
 
12990
- #include <queue>
12991
13045
 
12992
13046
  namespace duckdb {
12993
13047
  class ClientContext;
12994
13048
  class DataChunk;
12995
13049
  class PhysicalOperator;
12996
- class PhysicalOperatorState;
13050
+ class PipelineExecutor;
13051
+ class OperatorState;
12997
13052
  class ThreadContext;
12998
13053
  class Task;
12999
13054
 
13055
+ struct PipelineEventStack;
13000
13056
  struct ProducerToken;
13001
13057
 
13002
13058
  class Executor {
@@ -13010,8 +13066,10 @@ public:
13010
13066
  ClientContext &context;
13011
13067
 
13012
13068
  public:
13069
+ static Executor &Get(ClientContext &context);
13070
+
13013
13071
  void Initialize(PhysicalOperator *physical_plan);
13014
- void BuildPipelines(PhysicalOperator *op, Pipeline *parent);
13072
+ void BuildPipelines(PhysicalOperator *op, Pipeline *current);
13015
13073
 
13016
13074
  void Reset();
13017
13075
 
@@ -13020,8 +13078,15 @@ public:
13020
13078
  unique_ptr<DataChunk> FetchChunk();
13021
13079
 
13022
13080
  //! Push a new error
13023
- void PushError(const string &exception);
13024
- bool GetError(string &exception);
13081
+ void PushError(ExceptionType type, const string &exception);
13082
+ //! True if an error has been thrown
13083
+ bool HasError();
13084
+ //! Throw the exception that was pushed using PushError.
13085
+ //! Should only be called if HasError returns true
13086
+ void ThrowException();
13087
+
13088
+ //! Work on tasks for this specific executor, until there are no tasks remaining
13089
+ void WorkOnTasks();
13025
13090
 
13026
13091
  //! Flush a thread context into the client context
13027
13092
  void Flush(ThreadContext &context);
@@ -13029,24 +13094,79 @@ public:
13029
13094
  //! Returns the progress of the pipelines
13030
13095
  bool GetPipelinesProgress(int &current_progress);
13031
13096
 
13097
+ void CompletePipeline() {
13098
+ completed_pipelines++;
13099
+ }
13100
+ ProducerToken &GetToken() {
13101
+ return *producer;
13102
+ }
13103
+ void AddEvent(shared_ptr<Event> event);
13104
+
13105
+ void ReschedulePipelines(const vector<shared_ptr<Pipeline>> &pipelines, vector<shared_ptr<Event>> &events);
13106
+
13107
+ private:
13108
+ void ScheduleEvents();
13109
+ void ScheduleEventsInternal(const vector<shared_ptr<Pipeline>> &pipelines,
13110
+ unordered_map<Pipeline *, vector<shared_ptr<Pipeline>>> &child_pipelines,
13111
+ vector<shared_ptr<Event>> &events, bool main_schedule = true);
13112
+
13113
+ void SchedulePipeline(const shared_ptr<Pipeline> &pipeline,
13114
+ unordered_map<Pipeline *, PipelineEventStack> &event_map, vector<shared_ptr<Event>> &events,
13115
+ bool complete_pipeline);
13116
+ void ScheduleUnionPipeline(const shared_ptr<Pipeline> &pipeline, PipelineEventStack &stack,
13117
+ unordered_map<Pipeline *, PipelineEventStack> &event_map,
13118
+ vector<shared_ptr<Event>> &events);
13119
+ void ScheduleChildPipeline(Pipeline *parent, const shared_ptr<Pipeline> &pipeline,
13120
+ unordered_map<Pipeline *, PipelineEventStack> &event_map,
13121
+ vector<shared_ptr<Event>> &events);
13122
+ void ExtractPipelines(shared_ptr<Pipeline> &pipeline, vector<shared_ptr<Pipeline>> &result);
13123
+ bool NextExecutor();
13124
+
13125
+ void AddChildPipeline(Pipeline *current);
13126
+
13127
+ void VerifyPipeline(Pipeline &pipeline);
13128
+ void VerifyPipelines();
13129
+ void ThrowExceptionInternal();
13130
+
13032
13131
  private:
13033
13132
  PhysicalOperator *physical_plan;
13034
- unique_ptr<PhysicalOperatorState> physical_state;
13035
13133
 
13036
13134
  mutex executor_lock;
13037
13135
  //! The pipelines of the current query
13038
13136
  vector<shared_ptr<Pipeline>> pipelines;
13137
+ //! The root pipeline of the query
13138
+ vector<shared_ptr<Pipeline>> root_pipelines;
13139
+ //! The pipeline executor for the root pipeline
13140
+ unique_ptr<PipelineExecutor> root_executor;
13141
+ //! The current root pipeline index
13142
+ idx_t root_pipeline_idx;
13039
13143
  //! The producer of this query
13040
13144
  unique_ptr<ProducerToken> producer;
13041
13145
  //! Exceptions that occurred during the execution of the current query
13042
- vector<string> exceptions;
13146
+ vector<pair<ExceptionType, string>> exceptions;
13147
+ //! List of events
13148
+ vector<shared_ptr<Event>> events;
13043
13149
 
13044
13150
  //! The amount of completed pipelines of the query
13045
13151
  atomic<idx_t> completed_pipelines;
13046
13152
  //! The total amount of pipelines in the query
13047
13153
  idx_t total_pipelines;
13048
13154
 
13155
+ //! The adjacent union pipelines of each pipeline
13156
+ //! Union pipelines have the same sink, but can be run concurrently along with this pipeline
13157
+ unordered_map<Pipeline *, vector<shared_ptr<Pipeline>>> union_pipelines;
13158
+ //! Child pipelines of this pipeline
13159
+ //! Like union pipelines, child pipelines share the same sink
13160
+ //! Unlike union pipelines, child pipelines should be run AFTER their dependencies are completed
13161
+ //! i.e. they should be run after the dependencies are completed, but before finalize is called on the sink
13162
+ unordered_map<Pipeline *, vector<shared_ptr<Pipeline>>> child_pipelines;
13163
+ //! Dependencies of child pipelines
13164
+ unordered_map<Pipeline *, vector<Pipeline *>> child_dependencies;
13165
+
13166
+ //! Duplicate eliminated join scan dependencies
13049
13167
  unordered_map<PhysicalOperator *, Pipeline *> delim_join_dependencies;
13168
+
13169
+ //! Active recursive CTE node (if any)
13050
13170
  PhysicalOperator *recursive_cte;
13051
13171
  };
13052
13172
  } // namespace duckdb