duckdb 0.4.1-dev2230.0 → 0.4.1-dev2256.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/src/duckdb.cpp CHANGED
@@ -9579,7 +9579,7 @@ ParameterNotResolvedException::ParameterNotResolvedException()
9579
9579
 
9580
9580
 
9581
9581
  // LICENSE_CHANGE_BEGIN
9582
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
9582
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3
9583
9583
  // See the end of this file for a list
9584
9584
 
9585
9585
  /*
@@ -9621,7 +9621,7 @@ ParameterNotResolvedException::ParameterNotResolvedException()
9621
9621
 
9622
9622
 
9623
9623
  // LICENSE_CHANGE_BEGIN
9624
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
9624
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3
9625
9625
  // See the end of this file for a list
9626
9626
 
9627
9627
  // Formatting library for C++ - the core API
@@ -14405,7 +14405,7 @@ FMT_END_NAMESPACE
14405
14405
 
14406
14406
 
14407
14407
  // LICENSE_CHANGE_BEGIN
14408
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
14408
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3
14409
14409
  // See the end of this file for a list
14410
14410
 
14411
14411
  // Formatting library for C++ - legacy printf implementation
@@ -14424,7 +14424,7 @@ FMT_END_NAMESPACE
14424
14424
 
14425
14425
 
14426
14426
  // LICENSE_CHANGE_BEGIN
14427
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
14427
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3
14428
14428
  // See the end of this file for a list
14429
14429
 
14430
14430
  // Formatting library for C++ - std::ostream support
@@ -15613,7 +15613,7 @@ public:
15613
15613
 
15614
15614
 
15615
15615
  // LICENSE_CHANGE_BEGIN
15616
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3
15616
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #4
15617
15617
  // See the end of this file for a list
15618
15618
 
15619
15619
  /*
@@ -16977,7 +16977,7 @@ static constexpr const unsigned char GZIP_FLAG_UNSUPPORTED =
16977
16977
 
16978
16978
 
16979
16979
  // LICENSE_CHANGE_BEGIN
16980
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #4
16980
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5
16981
16981
  // See the end of this file for a list
16982
16982
 
16983
16983
  /* miniz.c 2.0.8 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing
@@ -18275,7 +18275,7 @@ void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const ch
18275
18275
 
18276
18276
 
18277
18277
  // LICENSE_CHANGE_BEGIN
18278
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #4
18278
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5
18279
18279
  // See the end of this file for a list
18280
18280
 
18281
18281
  //===----------------------------------------------------------------------===//
@@ -22447,7 +22447,7 @@ struct IntervalToStringCast {
22447
22447
 
22448
22448
 
22449
22449
  // LICENSE_CHANGE_BEGIN
22450
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5
22450
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6
22451
22451
  // See the end of this file for a list
22452
22452
 
22453
22453
  // duckdb_fast_float by Daniel Lemire
@@ -29342,7 +29342,7 @@ private:
29342
29342
 
29343
29343
 
29344
29344
  // LICENSE_CHANGE_BEGIN
29345
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6
29345
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #7
29346
29346
  // See the end of this file for a list
29347
29347
 
29348
29348
  /*
@@ -29469,7 +29469,7 @@ private:
29469
29469
 
29470
29470
 
29471
29471
  // LICENSE_CHANGE_BEGIN
29472
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6
29472
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #7
29473
29473
  // See the end of this file for a list
29474
29474
 
29475
29475
  /*
@@ -29558,7 +29558,7 @@ private:
29558
29558
 
29559
29559
 
29560
29560
  // LICENSE_CHANGE_BEGIN
29561
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6
29561
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #7
29562
29562
  // See the end of this file for a list
29563
29563
 
29564
29564
  /*
@@ -39300,7 +39300,7 @@ public:
39300
39300
 
39301
39301
 
39302
39302
  // LICENSE_CHANGE_BEGIN
39303
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3
39303
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #4
39304
39304
  // See the end of this file for a list
39305
39305
 
39306
39306
 
@@ -44128,133 +44128,6 @@ string hugeint_t::ToString() const {
44128
44128
  }
44129
44129
 
44130
44130
  } // namespace duckdb
44131
- //===----------------------------------------------------------------------===//
44132
- // DuckDB
44133
- //
44134
- // duckdb/common/types/hyperloglog.hpp
44135
- //
44136
- //
44137
- //===----------------------------------------------------------------------===//
44138
-
44139
-
44140
-
44141
-
44142
-
44143
-
44144
-
44145
- // LICENSE_CHANGE_BEGIN
44146
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #7
44147
- // See the end of this file for a list
44148
-
44149
- //===----------------------------------------------------------------------===//
44150
- // DuckDB
44151
- //
44152
- // third_party/hyperloglog/hyperloglog.hpp
44153
- //
44154
- //
44155
- //===----------------------------------------------------------------------===//
44156
-
44157
-
44158
-
44159
- #include <stdint.h>
44160
- #include <string.h>
44161
-
44162
- namespace duckdb_hll {
44163
-
44164
- /* Error codes */
44165
- #define HLL_C_OK 0
44166
- #define HLL_C_ERR -1
44167
-
44168
- typedef struct {
44169
- void *ptr;
44170
- } robj;
44171
-
44172
- //! Create a new empty HyperLogLog object
44173
- robj *hll_create(void);
44174
- //! Convert hll from sparse to dense
44175
- int hllSparseToDense(robj *o);
44176
- //! Destroy the specified HyperLogLog object
44177
- void hll_destroy(robj *obj);
44178
- //! Add an element with the specified amount of bytes to the HyperLogLog. Returns C_ERR on failure, otherwise returns 0
44179
- //! if the cardinality did not change, and 1 otherwise.
44180
- int hll_add(robj *o, unsigned char *ele, size_t elesize);
44181
- //! Returns the estimated amount of unique elements seen by the HyperLogLog. Returns C_OK on success, or C_ERR on
44182
- //! failure.
44183
- int hll_count(robj *o, size_t *result);
44184
- //! Merge hll_count HyperLogLog objects into a single one. Returns NULL on failure, or the new HLL object on success.
44185
- robj *hll_merge(robj **hlls, size_t hll_count);
44186
- //! Get size (in bytes) of the HLL
44187
- uint64_t get_size();
44188
-
44189
- uint64_t MurmurHash64A(const void *key, int len, unsigned int seed);
44190
-
44191
- } // namespace duckdb_hll
44192
-
44193
- namespace duckdb {
44194
-
44195
- void AddToLogsInternal(UnifiedVectorFormat &vdata, idx_t count, uint64_t indices[], uint8_t counts[], void ***logs[],
44196
- const SelectionVector *log_sel);
44197
-
44198
- void AddToSingleLogInternal(UnifiedVectorFormat &vdata, idx_t count, uint64_t indices[], uint8_t counts[], void *log);
44199
-
44200
- } // namespace duckdb
44201
-
44202
-
44203
- // LICENSE_CHANGE_END
44204
-
44205
-
44206
- namespace duckdb {
44207
-
44208
- enum class HLLStorageType { UNCOMPRESSED = 1 };
44209
-
44210
- class FieldWriter;
44211
- class FieldReader;
44212
-
44213
- //! The HyperLogLog class holds a HyperLogLog counter for approximate cardinality counting
44214
- class HyperLogLog {
44215
- public:
44216
- HyperLogLog();
44217
- ~HyperLogLog();
44218
- // implicit copying of HyperLogLog is not allowed
44219
- HyperLogLog(const HyperLogLog &) = delete;
44220
-
44221
- //! Adds an element of the specified size to the HyperLogLog counter
44222
- void Add(data_ptr_t element, idx_t size);
44223
- //! Return the count of this HyperLogLog counter
44224
- idx_t Count() const;
44225
- //! Merge this HyperLogLog counter with another counter to create a new one
44226
- unique_ptr<HyperLogLog> Merge(HyperLogLog &other);
44227
- HyperLogLog *MergePointer(HyperLogLog &other);
44228
- //! Merge a set of HyperLogLogs to create one big one
44229
- static unique_ptr<HyperLogLog> Merge(HyperLogLog logs[], idx_t count);
44230
- //! Get the size (in bytes) of a HLL
44231
- static idx_t GetSize();
44232
- //! Get pointer to the HLL
44233
- data_ptr_t GetPtr() const;
44234
- //! Get copy of the HLL
44235
- unique_ptr<HyperLogLog> Copy();
44236
- //! (De)Serialize the HLL
44237
- void Serialize(FieldWriter &writer) const;
44238
- static unique_ptr<HyperLogLog> Deserialize(FieldReader &reader);
44239
-
44240
- public:
44241
- //! Compute HLL hashes over vdata, and store them in 'hashes'
44242
- //! Then, compute register indices and prefix lengths, and also store them in 'hashes' as a pair of uint32_t
44243
- static void ProcessEntries(UnifiedVectorFormat &vdata, const LogicalType &type, uint64_t hashes[], uint8_t counts[],
44244
- idx_t count);
44245
- //! Add the indices and counts to the logs
44246
- static void AddToLogs(UnifiedVectorFormat &vdata, idx_t count, uint64_t indices[], uint8_t counts[],
44247
- HyperLogLog **logs[], const SelectionVector *log_sel);
44248
- //! Add the indices and counts to THIS log
44249
- void AddToLog(UnifiedVectorFormat &vdata, idx_t count, uint64_t indices[], uint8_t counts[]);
44250
-
44251
- private:
44252
- explicit HyperLogLog(void *hll);
44253
-
44254
- void *hll;
44255
- mutex lock;
44256
- };
44257
- } // namespace duckdb
44258
44131
 
44259
44132
 
44260
44133
 
@@ -68769,60 +68642,6 @@ public:
68769
68642
 
68770
68643
 
68771
68644
 
68772
- //===----------------------------------------------------------------------===//
68773
- // DuckDB
68774
- //
68775
- // duckdb/storage/statistics/distinct_statistics.hpp
68776
- //
68777
- //
68778
- //===----------------------------------------------------------------------===//
68779
-
68780
-
68781
-
68782
-
68783
-
68784
-
68785
-
68786
- namespace duckdb {
68787
- class Serializer;
68788
- class Deserializer;
68789
- class Vector;
68790
-
68791
- class DistinctStatistics : public BaseStatistics {
68792
- public:
68793
- DistinctStatistics();
68794
- explicit DistinctStatistics(unique_ptr<HyperLogLog> log, idx_t sample_count, idx_t total_count);
68795
-
68796
- //! The HLL of the table
68797
- unique_ptr<HyperLogLog> log;
68798
- //! How many values have been sampled into the HLL
68799
- atomic<idx_t> sample_count;
68800
- //! How many values have been inserted (before sampling)
68801
- atomic<idx_t> total_count;
68802
-
68803
- public:
68804
- void Merge(const BaseStatistics &other) override;
68805
-
68806
- unique_ptr<BaseStatistics> Copy() const override;
68807
-
68808
- void Serialize(Serializer &serializer) const override;
68809
- void Serialize(FieldWriter &writer) const override;
68810
-
68811
- static unique_ptr<DistinctStatistics> Deserialize(Deserializer &source);
68812
- static unique_ptr<DistinctStatistics> Deserialize(FieldReader &reader);
68813
-
68814
- void Update(Vector &update, idx_t count, bool sample = true);
68815
- void Update(UnifiedVectorFormat &update_data, const LogicalType &ptype, idx_t count, bool sample = true);
68816
-
68817
- string ToString() const override;
68818
- idx_t GetCount() const;
68819
-
68820
- private:
68821
- //! For distinct statistics we sample the input to speed up insertions
68822
- static constexpr const double SAMPLE_RATE = 0.1;
68823
- };
68824
-
68825
- } // namespace duckdb
68826
68645
 
68827
68646
 
68828
68647
  namespace duckdb {
@@ -70011,6 +69830,8 @@ string PhysicalComparisonJoin::ParamsToString() const {
70011
69830
  string op = ExpressionTypeToOperator(it.comparison);
70012
69831
  extra_info += it.left->GetName() + " " + op + " " + it.right->GetName() + "\n";
70013
69832
  }
69833
+ extra_info += "\nEC = " + std::to_string(estimated_props->GetCardinality()) + "\n";
69834
+ extra_info += "COST = " + std::to_string(estimated_props->GetCost()) + "\n";
70014
69835
  return extra_info;
70015
69836
  }
70016
69837
 
@@ -79729,6 +79550,7 @@ string PhysicalTableScan::ParamsToString() const {
79729
79550
  }
79730
79551
  }
79731
79552
  }
79553
+ result += "\nEC=" + to_string(estimated_cardinality) + "\n";
79732
79554
  return result;
79733
79555
  }
79734
79556
 
@@ -85254,98 +85076,149 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(unique_ptr<Logica
85254
85076
 
85255
85077
  unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalOperator &op) {
85256
85078
  op.estimated_cardinality = op.EstimateCardinality(context);
85079
+ unique_ptr<PhysicalOperator> plan = nullptr;
85080
+
85257
85081
  switch (op.type) {
85258
85082
  case LogicalOperatorType::LOGICAL_GET:
85259
- return CreatePlan((LogicalGet &)op);
85083
+ plan = CreatePlan((LogicalGet &)op);
85084
+ break;
85260
85085
  case LogicalOperatorType::LOGICAL_PROJECTION:
85261
- return CreatePlan((LogicalProjection &)op);
85086
+ plan = CreatePlan((LogicalProjection &)op);
85087
+ break;
85262
85088
  case LogicalOperatorType::LOGICAL_EMPTY_RESULT:
85263
- return CreatePlan((LogicalEmptyResult &)op);
85089
+ plan = CreatePlan((LogicalEmptyResult &)op);
85090
+ break;
85264
85091
  case LogicalOperatorType::LOGICAL_FILTER:
85265
- return CreatePlan((LogicalFilter &)op);
85092
+ plan = CreatePlan((LogicalFilter &)op);
85093
+ break;
85266
85094
  case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY:
85267
- return CreatePlan((LogicalAggregate &)op);
85095
+ plan = CreatePlan((LogicalAggregate &)op);
85096
+ break;
85268
85097
  case LogicalOperatorType::LOGICAL_WINDOW:
85269
- return CreatePlan((LogicalWindow &)op);
85098
+ plan = CreatePlan((LogicalWindow &)op);
85099
+ break;
85270
85100
  case LogicalOperatorType::LOGICAL_UNNEST:
85271
- return CreatePlan((LogicalUnnest &)op);
85101
+ plan = CreatePlan((LogicalUnnest &)op);
85102
+ break;
85272
85103
  case LogicalOperatorType::LOGICAL_LIMIT:
85273
- return CreatePlan((LogicalLimit &)op);
85104
+ plan = CreatePlan((LogicalLimit &)op);
85105
+ break;
85274
85106
  case LogicalOperatorType::LOGICAL_LIMIT_PERCENT:
85275
- return CreatePlan((LogicalLimitPercent &)op);
85107
+ plan = CreatePlan((LogicalLimitPercent &)op);
85108
+ break;
85276
85109
  case LogicalOperatorType::LOGICAL_SAMPLE:
85277
- return CreatePlan((LogicalSample &)op);
85110
+ plan = CreatePlan((LogicalSample &)op);
85111
+ break;
85278
85112
  case LogicalOperatorType::LOGICAL_ORDER_BY:
85279
- return CreatePlan((LogicalOrder &)op);
85113
+ plan = CreatePlan((LogicalOrder &)op);
85114
+ break;
85280
85115
  case LogicalOperatorType::LOGICAL_TOP_N:
85281
- return CreatePlan((LogicalTopN &)op);
85116
+ plan = CreatePlan((LogicalTopN &)op);
85117
+ break;
85282
85118
  case LogicalOperatorType::LOGICAL_COPY_TO_FILE:
85283
- return CreatePlan((LogicalCopyToFile &)op);
85119
+ plan = CreatePlan((LogicalCopyToFile &)op);
85120
+ break;
85284
85121
  case LogicalOperatorType::LOGICAL_DUMMY_SCAN:
85285
- return CreatePlan((LogicalDummyScan &)op);
85122
+ plan = CreatePlan((LogicalDummyScan &)op);
85123
+ break;
85286
85124
  case LogicalOperatorType::LOGICAL_ANY_JOIN:
85287
- return CreatePlan((LogicalAnyJoin &)op);
85125
+ plan = CreatePlan((LogicalAnyJoin &)op);
85126
+ break;
85288
85127
  case LogicalOperatorType::LOGICAL_DELIM_JOIN:
85289
- return CreatePlan((LogicalDelimJoin &)op);
85128
+ plan = CreatePlan((LogicalDelimJoin &)op);
85129
+ break;
85290
85130
  case LogicalOperatorType::LOGICAL_COMPARISON_JOIN:
85291
- return CreatePlan((LogicalComparisonJoin &)op);
85131
+ plan = CreatePlan((LogicalComparisonJoin &)op);
85132
+ break;
85292
85133
  case LogicalOperatorType::LOGICAL_CROSS_PRODUCT:
85293
- return CreatePlan((LogicalCrossProduct &)op);
85134
+ plan = CreatePlan((LogicalCrossProduct &)op);
85135
+ break;
85294
85136
  case LogicalOperatorType::LOGICAL_UNION:
85295
85137
  case LogicalOperatorType::LOGICAL_EXCEPT:
85296
85138
  case LogicalOperatorType::LOGICAL_INTERSECT:
85297
- return CreatePlan((LogicalSetOperation &)op);
85139
+ plan = CreatePlan((LogicalSetOperation &)op);
85140
+ break;
85298
85141
  case LogicalOperatorType::LOGICAL_INSERT:
85299
- return CreatePlan((LogicalInsert &)op);
85142
+ plan = CreatePlan((LogicalInsert &)op);
85143
+ break;
85300
85144
  case LogicalOperatorType::LOGICAL_DELETE:
85301
- return CreatePlan((LogicalDelete &)op);
85145
+ plan = CreatePlan((LogicalDelete &)op);
85146
+ break;
85302
85147
  case LogicalOperatorType::LOGICAL_CHUNK_GET:
85303
- return CreatePlan((LogicalColumnDataGet &)op);
85148
+ plan = CreatePlan((LogicalColumnDataGet &)op);
85149
+ break;
85304
85150
  case LogicalOperatorType::LOGICAL_DELIM_GET:
85305
- return CreatePlan((LogicalDelimGet &)op);
85151
+ plan = CreatePlan((LogicalDelimGet &)op);
85152
+ break;
85306
85153
  case LogicalOperatorType::LOGICAL_EXPRESSION_GET:
85307
- return CreatePlan((LogicalExpressionGet &)op);
85154
+ plan = CreatePlan((LogicalExpressionGet &)op);
85155
+ break;
85308
85156
  case LogicalOperatorType::LOGICAL_UPDATE:
85309
- return CreatePlan((LogicalUpdate &)op);
85157
+ plan = CreatePlan((LogicalUpdate &)op);
85158
+ break;
85310
85159
  case LogicalOperatorType::LOGICAL_CREATE_TABLE:
85311
- return CreatePlan((LogicalCreateTable &)op);
85160
+ plan = CreatePlan((LogicalCreateTable &)op);
85161
+ break;
85312
85162
  case LogicalOperatorType::LOGICAL_CREATE_INDEX:
85313
- return CreatePlan((LogicalCreateIndex &)op);
85163
+ plan = CreatePlan((LogicalCreateIndex &)op);
85164
+ break;
85314
85165
  case LogicalOperatorType::LOGICAL_EXPLAIN:
85315
- return CreatePlan((LogicalExplain &)op);
85166
+ plan = CreatePlan((LogicalExplain &)op);
85167
+ break;
85316
85168
  case LogicalOperatorType::LOGICAL_SHOW:
85317
- return CreatePlan((LogicalShow &)op);
85169
+ plan = CreatePlan((LogicalShow &)op);
85170
+ break;
85318
85171
  case LogicalOperatorType::LOGICAL_DISTINCT:
85319
- return CreatePlan((LogicalDistinct &)op);
85172
+ plan = CreatePlan((LogicalDistinct &)op);
85173
+ break;
85320
85174
  case LogicalOperatorType::LOGICAL_PREPARE:
85321
- return CreatePlan((LogicalPrepare &)op);
85175
+ plan = CreatePlan((LogicalPrepare &)op);
85176
+ break;
85322
85177
  case LogicalOperatorType::LOGICAL_EXECUTE:
85323
- return CreatePlan((LogicalExecute &)op);
85178
+ plan = CreatePlan((LogicalExecute &)op);
85179
+ break;
85324
85180
  case LogicalOperatorType::LOGICAL_CREATE_VIEW:
85325
85181
  case LogicalOperatorType::LOGICAL_CREATE_SEQUENCE:
85326
85182
  case LogicalOperatorType::LOGICAL_CREATE_SCHEMA:
85327
85183
  case LogicalOperatorType::LOGICAL_CREATE_MACRO:
85328
85184
  case LogicalOperatorType::LOGICAL_CREATE_TYPE:
85329
- return CreatePlan((LogicalCreate &)op);
85185
+ plan = CreatePlan((LogicalCreate &)op);
85186
+ break;
85330
85187
  case LogicalOperatorType::LOGICAL_PRAGMA:
85331
- return CreatePlan((LogicalPragma &)op);
85188
+ plan = CreatePlan((LogicalPragma &)op);
85189
+ break;
85332
85190
  case LogicalOperatorType::LOGICAL_TRANSACTION:
85333
85191
  case LogicalOperatorType::LOGICAL_ALTER:
85334
85192
  case LogicalOperatorType::LOGICAL_DROP:
85335
85193
  case LogicalOperatorType::LOGICAL_VACUUM:
85336
85194
  case LogicalOperatorType::LOGICAL_LOAD:
85337
- return CreatePlan((LogicalSimple &)op);
85195
+ plan = CreatePlan((LogicalSimple &)op);
85196
+ break;
85338
85197
  case LogicalOperatorType::LOGICAL_RECURSIVE_CTE:
85339
- return CreatePlan((LogicalRecursiveCTE &)op);
85198
+ plan = CreatePlan((LogicalRecursiveCTE &)op);
85199
+ break;
85340
85200
  case LogicalOperatorType::LOGICAL_CTE_REF:
85341
- return CreatePlan((LogicalCTERef &)op);
85201
+ plan = CreatePlan((LogicalCTERef &)op);
85202
+ break;
85342
85203
  case LogicalOperatorType::LOGICAL_EXPORT:
85343
- return CreatePlan((LogicalExport &)op);
85204
+ plan = CreatePlan((LogicalExport &)op);
85205
+ break;
85344
85206
  case LogicalOperatorType::LOGICAL_SET:
85345
- return CreatePlan((LogicalSet &)op);
85346
- default:
85207
+ plan = CreatePlan((LogicalSet &)op);
85208
+ break;
85209
+ default: {
85347
85210
  throw NotImplementedException("Unimplemented logical operator type!");
85348
85211
  }
85212
+ }
85213
+
85214
+ if (op.estimated_props) {
85215
+ plan->estimated_cardinality = op.estimated_props->GetCardinality();
85216
+ plan->estimated_props = op.estimated_props->Copy();
85217
+ } else {
85218
+ plan->estimated_props = make_unique<EstimatedProperties>();
85219
+ }
85220
+
85221
+ return plan;
85349
85222
  }
85350
85223
 
85351
85224
  } // namespace duckdb
@@ -141712,6 +141585,786 @@ void StreamQueryResult::Close() {
141712
141585
  context.reset();
141713
141586
  }
141714
141587
 
141588
+ } // namespace duckdb
141589
+
141590
+
141591
+ //===----------------------------------------------------------------------===//
141592
+ // DuckDB
141593
+ //
141594
+ // duckdb/optimizer/join_order_optimizer.hpp
141595
+ //
141596
+ //
141597
+ //===----------------------------------------------------------------------===//
141598
+
141599
+
141600
+
141601
+
141602
+
141603
+
141604
+
141605
+
141606
+
141607
+
141608
+
141609
+ //===----------------------------------------------------------------------===//
141610
+ // DuckDB
141611
+ //
141612
+ // duckdb/optimizer/cardinality_estimator.hpp
141613
+ //
141614
+ //
141615
+ //===----------------------------------------------------------------------===//
141616
+
141617
+
141618
+
141619
+
141620
+
141621
+
141622
+
141623
+
141624
+
141625
+ namespace duckdb {
141626
+
141627
+ struct RelationAttributes {
141628
+ string original_name;
141629
+ // the relation columns used in join filters
141630
+ // Needed when iterating over columns and initializing total domain values.
141631
+ unordered_set<idx_t> columns;
141632
+ double cardinality;
141633
+ };
141634
+
141635
+ struct RelationsToTDom {
141636
+ //! column binding sets that are equivalent in a join plan.
141637
+ //! if you have A.x = B.y and B.y = C.z, then one set is {A.x, B.y, C.z}.
141638
+ column_binding_set_t equivalent_relations;
141639
+ //! the estimated total domains of the equivalent relations determined using HLL
141640
+ idx_t tdom_hll;
141641
+ //! the estimated total domains of each relation without using HLL
141642
+ idx_t tdom_no_hll;
141643
+ bool has_tdom_hll;
141644
+ vector<FilterInfo *> filters;
141645
+
141646
+ RelationsToTDom(column_binding_set_t column_binding_set)
141647
+ : equivalent_relations(column_binding_set), tdom_hll(0), tdom_no_hll(NumericLimits<idx_t>::Maximum()),
141648
+ has_tdom_hll(false) {};
141649
+ };
141650
+
141651
+ struct NodeOp {
141652
+ unique_ptr<JoinNode> node;
141653
+ LogicalOperator *op;
141654
+
141655
+ NodeOp(unique_ptr<JoinNode> node, LogicalOperator *op) : node(move(node)), op(op) {};
141656
+ };
141657
+
141658
+ struct Subgraph2Denominator {
141659
+ unordered_set<idx_t> relations;
141660
+ double denom;
141661
+
141662
+ Subgraph2Denominator() : relations(), denom(1) {};
141663
+ };
141664
+
141665
+ class CardinalityEstimator {
141666
+ public:
141667
+ explicit CardinalityEstimator(ClientContext &context) : context(context) {
141668
+ }
141669
+
141670
+ private:
141671
+ ClientContext &context;
141672
+
141673
+ //! A mapping of relation id -> RelationAttributes
141674
+ unordered_map<idx_t, RelationAttributes> relation_attributes;
141675
+ //! A mapping of (relation, bound_column) -> (actual table, actual column)
141676
+ column_binding_map_t<ColumnBinding> relation_column_to_original_column;
141677
+
141678
+ vector<RelationsToTDom> relations_to_tdoms;
141679
+
141680
+ static constexpr double DEFAULT_SELECTIVITY = 0.2;
141681
+
141682
+ public:
141683
+ static void VerifySymmetry(JoinNode *result, JoinNode *entry);
141684
+
141685
+ void AssertEquivalentRelationSize();
141686
+
141687
+ //! given a binding of (relation, column) used for DP, and a (table, column) in that catalog
141688
+ //! Add the key value entry into the relation_column_to_original_column
141689
+ void AddRelationToColumnMapping(ColumnBinding key, ColumnBinding value);
141690
+ //! Add a column to the relation_to_columns map.
141691
+ void AddColumnToRelationMap(idx_t table_index, idx_t column_index);
141692
+ //! Dump all bindings in relation_column_to_original_column into the child_binding_map
141693
+ // If you have a non-reorderable join, this function is used to keep track of bindings
141694
+ // in the child join plan.
141695
+ void CopyRelationMap(column_binding_map_t<ColumnBinding> &child_binding_map);
141696
+ void MergeBindings(idx_t, idx_t relation_id, vector<column_binding_map_t<ColumnBinding>> &child_binding_maps);
141697
+ void AddRelationColumnMapping(LogicalGet *get, idx_t relation_id);
141698
+
141699
+ void InitTotalDomains();
141700
+ void UpdateTotalDomains(JoinNode *node, LogicalOperator *op);
141701
+ void InitEquivalentRelations(vector<unique_ptr<FilterInfo>> *filter_infos);
141702
+
141703
+ void InitCardinalityEstimatorProps(vector<struct NodeOp> *node_ops, vector<unique_ptr<FilterInfo>> *filter_infos);
141704
+ double EstimateCardinalityWithSet(JoinRelationSet *new_set);
141705
+ void EstimateBaseTableCardinality(JoinNode *node, LogicalOperator *op);
141706
+ double EstimateCrossProduct(const JoinNode *left, const JoinNode *right);
141707
+ static double ComputeCost(JoinNode *left, JoinNode *right, double expected_cardinality);
141708
+
141709
+ private:
141710
+ bool SingleColumnFilter(FilterInfo *filter_info);
141711
+ //! Filter & bindings -> list of indexes into the equivalent_relations array.
141712
+ // The column binding set at each index is an equivalence set.
141713
+ vector<idx_t> DetermineMatchingEquivalentSets(FilterInfo *filter_info);
141714
+
141715
+ //! Given a filter, add the column bindings to the matching equivalent set at the index
141716
+ //! given in matching equivalent sets.
141717
+ //! If there are multiple equivalence sets, they are merged.
141718
+ void AddToEquivalenceSets(FilterInfo *filter_info, vector<idx_t> matching_equivalent_sets);
141719
+
141720
+ TableFilterSet *GetTableFilters(LogicalOperator *op);
141721
+
141722
+ idx_t InspectConjunctionAND(idx_t cardinality, idx_t column_index, ConjunctionAndFilter *fil,
141723
+ unique_ptr<BaseStatistics> base_stats);
141724
+ idx_t InspectConjunctionOR(idx_t cardinality, idx_t column_index, ConjunctionOrFilter *fil,
141725
+ unique_ptr<BaseStatistics> base_stats);
141726
+ idx_t InspectTableFilters(idx_t cardinality, LogicalOperator *op, TableFilterSet *table_filters);
141727
+ };
141728
+
141729
+ } // namespace duckdb
141730
+
141731
+
141732
+ #include <functional>
141733
+
141734
+ namespace duckdb {
141735
+
141736
+ class JoinOrderOptimizer {
141737
+ public:
141738
+ explicit JoinOrderOptimizer(ClientContext &context)
141739
+ : context(context), cardinality_estimator(context), full_plan_found(false), must_update_full_plan(false) {
141740
+ }
141741
+
141742
+ //! Perform join reordering inside a plan
141743
+ unique_ptr<LogicalOperator> Optimize(unique_ptr<LogicalOperator> plan);
141744
+
141745
+ unique_ptr<JoinNode> CreateJoinTree(JoinRelationSet *set, const vector<NeighborInfo *> &possible_connections,
141746
+ JoinNode *left, JoinNode *right);
141747
+
141748
+ private:
141749
+ ClientContext &context;
141750
+ //! The total amount of join pairs that have been considered
141751
+ idx_t pairs = 0;
141752
+ //! Set of all relations considered in the join optimizer
141753
+ vector<unique_ptr<SingleJoinRelation>> relations;
141754
+ //! A mapping of base table index -> index into relations array (relation number)
141755
+ unordered_map<idx_t, idx_t> relation_mapping;
141756
+ //! A structure holding all the created JoinRelationSet objects
141757
+ JoinRelationSetManager set_manager;
141758
+ //! The set of edges used in the join optimizer
141759
+ QueryGraph query_graph;
141760
+ //! The optimal join plan found for the specific JoinRelationSet*
141761
+ unordered_map<JoinRelationSet *, unique_ptr<JoinNode>> plans;
141762
+
141763
+ //! The set of filters extracted from the query graph
141764
+ vector<unique_ptr<Expression>> filters;
141765
+ //! The set of filter infos created from the extracted filters
141766
+ vector<unique_ptr<FilterInfo>> filter_infos;
141767
+ //! A map of all expressions a given expression has to be equivalent to. This is used to add "implied join edges".
141768
+ //! i.e. in the join A=B AND B=C, the equivalence set of {B} is {A, C}, thus we can add an implied join edge {A <->
141769
+ //! C}
141770
+ expression_map_t<vector<FilterInfo *>> equivalence_sets;
141771
+
141772
+ CardinalityEstimator cardinality_estimator;
141773
+
141774
+ bool full_plan_found;
141775
+ bool must_update_full_plan;
141776
+ unordered_set<JoinNode *> join_nodes_in_full_plan;
141777
+
141778
+ //! Extract the bindings referred to by an Expression
141779
+ bool ExtractBindings(Expression &expression, unordered_set<idx_t> &bindings);
141780
+
141781
+ //! Get column bindings from a filter
141782
+ void GetColumnBindings(Expression &expression, ColumnBinding &left_binding, ColumnBinding &right_binding);
141783
+
141784
+ //! Traverse the query tree to find (1) base relations, (2) existing join conditions and (3) filters that can be
141785
+ //! rewritten into joins. Returns true if there are joins in the tree that can be reordered, false otherwise.
141786
+ bool ExtractJoinRelations(LogicalOperator &input_op, vector<LogicalOperator *> &filter_operators,
141787
+ LogicalOperator *parent = nullptr);
141788
+
141789
+ //! Emit a pair as a potential join candidate. Returns the best plan found for the (left, right) connection (either
141790
+ //! the newly created plan, or an existing plan)
141791
+ JoinNode *EmitPair(JoinRelationSet *left, JoinRelationSet *right, const vector<NeighborInfo *> &info);
141792
+ //! Tries to emit a potential join candidate pair. Returns false if too many pairs have already been emitted,
141793
+ //! cancelling the dynamic programming step.
141794
+ bool TryEmitPair(JoinRelationSet *left, JoinRelationSet *right, const vector<NeighborInfo *> &info);
141795
+
141796
+ bool EnumerateCmpRecursive(JoinRelationSet *left, JoinRelationSet *right, unordered_set<idx_t> exclusion_set);
141797
+ //! Emit a relation set node
141798
+ bool EmitCSG(JoinRelationSet *node);
141799
+ //! Enumerate the possible connected subgraphs that can be joined together in the join graph
141800
+ bool EnumerateCSGRecursive(JoinRelationSet *node, unordered_set<idx_t> &exclusion_set);
141801
+ //! Rewrite a logical query plan given the join plan
141802
+ unique_ptr<LogicalOperator> RewritePlan(unique_ptr<LogicalOperator> plan, JoinNode *node);
141803
+ //! Generate cross product edges inside the side
141804
+ void GenerateCrossProducts();
141805
+ //! Perform the join order solving
141806
+ void SolveJoinOrder();
141807
+ //! Solve the join order exactly using dynamic programming. Returns true if it was completed successfully (i.e. did
141808
+ //! not time-out)
141809
+ bool SolveJoinOrderExactly();
141810
+ //! Solve the join order approximately using a greedy algorithm
141811
+ void SolveJoinOrderApproximately();
141812
+
141813
+ void UpdateDPTree(JoinNode *new_plan);
141814
+
141815
+ void UpdateJoinNodesInFullPlan(JoinNode *node);
141816
+
141817
+ std::pair<JoinRelationSet *, unique_ptr<LogicalOperator>>
141818
+ GenerateJoins(vector<unique_ptr<LogicalOperator>> &extracted_relations, JoinNode *node);
141819
+ };
141820
+
141821
+ } // namespace duckdb
141822
+
141823
+
141824
+
141825
+
141826
+
141827
+
141828
+
141829
+
141830
+ namespace duckdb {
141831
+
141832
+ static TableCatalogEntry *GetCatalogTableEntry(LogicalOperator *op) {
141833
+ if (op->type == LogicalOperatorType::LOGICAL_GET) {
141834
+ auto get = (LogicalGet *)op;
141835
+ TableCatalogEntry *entry = get->GetTable();
141836
+ return entry;
141837
+ }
141838
+ for (auto &child : op->children) {
141839
+ TableCatalogEntry *entry = GetCatalogTableEntry(child.get());
141840
+ if (entry != nullptr) {
141841
+ return entry;
141842
+ }
141843
+ }
141844
+ return nullptr;
141845
+ }
141846
+
141847
+ bool CardinalityEstimator::SingleColumnFilter(FilterInfo *filter_info) {
141848
+ if (filter_info->left_set && filter_info->right_set) {
141849
+ // Both set
141850
+ return false;
141851
+ }
141852
+ // Filter on one relation, (i.e string or range filter on a column).
141853
+ // Grab the first relation and add it to the the equivalence_relations
141854
+ D_ASSERT(filter_info->set->count >= 1);
141855
+ for (const RelationsToTDom &r2tdom : relations_to_tdoms) {
141856
+ auto &i_set = r2tdom.equivalent_relations;
141857
+ if (i_set.find(filter_info->left_binding) != i_set.end()) {
141858
+ // found an equivalent filter
141859
+ return true;
141860
+ }
141861
+ }
141862
+ auto key = ColumnBinding(filter_info->left_binding.table_index, filter_info->left_binding.column_index);
141863
+ column_binding_set_t tmp({key});
141864
+ relations_to_tdoms.emplace_back(RelationsToTDom(tmp));
141865
+ return true;
141866
+ }
141867
+
141868
+ vector<idx_t> CardinalityEstimator::DetermineMatchingEquivalentSets(FilterInfo *filter_info) {
141869
+ vector<idx_t> matching_equivalent_sets;
141870
+ auto equivalent_relation_index = 0;
141871
+
141872
+ for (const RelationsToTDom &r2tdom : relations_to_tdoms) {
141873
+ auto &i_set = r2tdom.equivalent_relations;
141874
+ if (i_set.find(filter_info->left_binding) != i_set.end()) {
141875
+ matching_equivalent_sets.push_back(equivalent_relation_index);
141876
+ } else if (i_set.find(filter_info->right_binding) != i_set.end()) {
141877
+ // don't add both left and right to the matching_equivalent_sets
141878
+ // since both left and right get added to that index anyway.
141879
+ matching_equivalent_sets.push_back(equivalent_relation_index);
141880
+ }
141881
+ equivalent_relation_index++;
141882
+ }
141883
+ return matching_equivalent_sets;
141884
+ }
141885
+
141886
+ void CardinalityEstimator::AddToEquivalenceSets(FilterInfo *filter_info, vector<idx_t> matching_equivalent_sets) {
141887
+ D_ASSERT(matching_equivalent_sets.size() <= 2);
141888
+ if (matching_equivalent_sets.size() > 1) {
141889
+ // an equivalence relation is connecting to sets of equivalence relations
141890
+ // so push all relations from the second set into the first. Later we will delete
141891
+ // the second set.
141892
+ for (ColumnBinding i : relations_to_tdoms.at(matching_equivalent_sets[1]).equivalent_relations) {
141893
+ relations_to_tdoms.at(matching_equivalent_sets[0]).equivalent_relations.insert(i);
141894
+ }
141895
+ relations_to_tdoms.at(matching_equivalent_sets[1]).equivalent_relations.clear();
141896
+ relations_to_tdoms.at(matching_equivalent_sets[0]).filters.push_back(filter_info);
141897
+ // add all values of one set to the other, delete the empty one
141898
+ } else if (matching_equivalent_sets.size() == 1) {
141899
+ auto &tdom_i = relations_to_tdoms.at(matching_equivalent_sets.at(0));
141900
+ tdom_i.equivalent_relations.insert(filter_info->left_binding);
141901
+ tdom_i.equivalent_relations.insert(filter_info->right_binding);
141902
+ tdom_i.filters.push_back(filter_info);
141903
+ } else if (matching_equivalent_sets.empty()) {
141904
+ column_binding_set_t tmp;
141905
+ tmp.insert(filter_info->left_binding);
141906
+ tmp.insert(filter_info->right_binding);
141907
+ relations_to_tdoms.emplace_back(RelationsToTDom(tmp));
141908
+ relations_to_tdoms.back().filters.push_back(filter_info);
141909
+ }
141910
+ }
141911
+
141912
+ void CardinalityEstimator::AddRelationToColumnMapping(ColumnBinding key, ColumnBinding value) {
141913
+ relation_column_to_original_column[key] = value;
141914
+ }
141915
+
141916
+ void CardinalityEstimator::CopyRelationMap(column_binding_map_t<ColumnBinding> &child_binding_map) {
141917
+ for (auto &binding_map : relation_column_to_original_column) {
141918
+ child_binding_map[binding_map.first] = binding_map.second;
141919
+ }
141920
+ }
141921
+
141922
+ void CardinalityEstimator::AddColumnToRelationMap(idx_t table_index, idx_t column_index) {
141923
+ relation_attributes[table_index].columns.insert(column_index);
141924
+ }
141925
+
141926
+ void CardinalityEstimator::InitEquivalentRelations(vector<unique_ptr<FilterInfo>> *filter_infos) {
141927
+ // For each filter, we fill keep track of the index of the equivalent relation set
141928
+ // the left and right relation needs to be added to.
141929
+ for (auto &filter : *filter_infos) {
141930
+ if (SingleColumnFilter(filter.get())) {
141931
+ continue;
141932
+ }
141933
+ D_ASSERT(filter->left_set->count >= 1);
141934
+ D_ASSERT(filter->right_set->count >= 1);
141935
+
141936
+ auto matching_equivalent_sets = DetermineMatchingEquivalentSets(filter.get());
141937
+ AddToEquivalenceSets(filter.get(), matching_equivalent_sets);
141938
+ }
141939
+ }
141940
+
141941
+ void CardinalityEstimator::VerifySymmetry(JoinNode *result, JoinNode *entry) {
141942
+ if (result->GetCardinality() != entry->GetCardinality()) {
141943
+ // Currently it's possible that some entries are cartesian joins.
141944
+ // When this is the case, you don't always have symmetry, but
141945
+ // if the cost of the result is less, then just assure the cardinality
141946
+ // is also less, then you have the same effect of symmetry.
141947
+ D_ASSERT(ceil(result->GetCardinality()) <= ceil(entry->GetCardinality()) ||
141948
+ floor(result->GetCardinality()) <= floor(entry->GetCardinality()));
141949
+ }
141950
+ }
141951
+
141952
+ void CardinalityEstimator::InitTotalDomains() {
141953
+ auto remove_start = std::remove_if(relations_to_tdoms.begin(), relations_to_tdoms.end(),
141954
+ [](RelationsToTDom &r_2_tdom) { return r_2_tdom.equivalent_relations.empty(); });
141955
+ relations_to_tdoms.erase(remove_start, relations_to_tdoms.end());
141956
+ }
141957
+
141958
+ double CardinalityEstimator::ComputeCost(JoinNode *left, JoinNode *right, double expected_cardinality) {
141959
+ return expected_cardinality + left->GetCost() + right->GetCost();
141960
+ }
141961
+
141962
+ double CardinalityEstimator::EstimateCrossProduct(const JoinNode *left, const JoinNode *right) {
141963
+ // need to explicity use double here, otherwise auto converts it to an int, then
141964
+ // there is an autocast in the return.
141965
+ return left->GetCardinality() >= (NumericLimits<double>::Maximum() / right->GetCardinality())
141966
+ ? NumericLimits<double>::Maximum()
141967
+ : left->GetCardinality() * right->GetCardinality();
141968
+ }
141969
+
141970
+ void CardinalityEstimator::AddRelationColumnMapping(LogicalGet *get, idx_t relation_id) {
141971
+ for (idx_t it = 0; it < get->column_ids.size(); it++) {
141972
+ auto key = ColumnBinding(relation_id, it);
141973
+ auto value = ColumnBinding(get->table_index, get->column_ids[it]);
141974
+ AddRelationToColumnMapping(key, value);
141975
+ }
141976
+ }
141977
+
141978
+ void UpdateDenom(Subgraph2Denominator *relation_2_denom, RelationsToTDom *relation_to_tdom) {
141979
+ relation_2_denom->denom *=
141980
+ relation_to_tdom->has_tdom_hll ? relation_to_tdom->tdom_hll : relation_to_tdom->tdom_no_hll;
141981
+ }
141982
+
141983
+ void FindSubgraphMatchAndMerge(Subgraph2Denominator &merge_to, idx_t find_me,
141984
+ vector<Subgraph2Denominator>::iterator subgraph,
141985
+ vector<Subgraph2Denominator>::iterator end) {
141986
+ for (; subgraph != end; subgraph++) {
141987
+ if (subgraph->relations.count(find_me) >= 1) {
141988
+ for (auto &relation : subgraph->relations) {
141989
+ merge_to.relations.insert(relation);
141990
+ }
141991
+ subgraph->relations.clear();
141992
+ merge_to.denom *= subgraph->denom;
141993
+ return;
141994
+ }
141995
+ }
141996
+ }
141997
+
141998
+ double CardinalityEstimator::EstimateCardinalityWithSet(JoinRelationSet *new_set) {
141999
+ double numerator = 1;
142000
+ unordered_set<idx_t> actual_set;
142001
+ for (idx_t i = 0; i < new_set->count; i++) {
142002
+ numerator *= relation_attributes[new_set->relations[i]].cardinality;
142003
+ actual_set.insert(new_set->relations[i]);
142004
+ }
142005
+ vector<Subgraph2Denominator> subgraphs;
142006
+ bool done = false;
142007
+ bool found_match = false;
142008
+
142009
+ // Finding the denominator is tricky. You need to go through the tdoms in decreasing order
142010
+ // Then loop through all filters in the equivalence set of the tdom to see if both the
142011
+ // left and right relations are in the new set, if so you can use that filter.
142012
+ // You must also make sure that the filters all relations in the given set, so we use subgraphs
142013
+ // that should eventually merge into one connected graph that joins all the relations
142014
+ // TODO: Don't implement a method to cache subgraphs so you don't have to build them up every
142015
+ // time the cardinality of a new set is requested
142016
+
142017
+ // relations_to_tdoms has already been sorted.
142018
+ for (auto &relation_2_tdom : relations_to_tdoms) {
142019
+ // loop through each filter in the tdom.
142020
+ if (done) {
142021
+ break;
142022
+ }
142023
+ for (auto &filter : relation_2_tdom.filters) {
142024
+ if (actual_set.count(filter->left_binding.table_index) == 0 ||
142025
+ actual_set.count(filter->right_binding.table_index) == 0) {
142026
+ continue;
142027
+ }
142028
+ // the join filter is on relations in the new set.
142029
+ found_match = false;
142030
+ vector<Subgraph2Denominator>::iterator it;
142031
+ for (it = subgraphs.begin(); it != subgraphs.end(); it++) {
142032
+ auto left_in = it->relations.count(filter->left_binding.table_index);
142033
+ auto right_in = it->relations.count(filter->right_binding.table_index);
142034
+ // if both left and right bindings are in the subgraph, continue
142035
+ // if both left and right bindings are *not* in the subgraph, continue
142036
+ if (!(left_in ^ right_in)) {
142037
+ continue;
142038
+ }
142039
+ idx_t find_table;
142040
+ if (left_in) {
142041
+ find_table = filter->right_binding.table_index;
142042
+ } else {
142043
+ D_ASSERT(right_in);
142044
+ find_table = filter->left_binding.table_index;
142045
+ }
142046
+ auto next_subgraph = it + 1;
142047
+ // iterate through other subgraphs and merge.
142048
+ FindSubgraphMatchAndMerge(*it, find_table, next_subgraph, subgraphs.end());
142049
+ // Now insert the right binding and update denominator with the
142050
+ // tdom of the filter
142051
+ it->relations.insert(find_table);
142052
+ UpdateDenom(&(*it), &relation_2_tdom);
142053
+ found_match = true;
142054
+ break;
142055
+ }
142056
+ // means that the filter joins relations in the given set, but there is no
142057
+ // connection to any subgraph in subgraphs. Add a new subgraph, and maybe later there will be
142058
+ // a connection.
142059
+ if (!found_match) {
142060
+ subgraphs.emplace_back(Subgraph2Denominator());
142061
+ auto subgraph = &subgraphs.back();
142062
+ subgraph->relations.insert(filter->left_binding.table_index);
142063
+ subgraph->relations.insert(filter->right_binding.table_index);
142064
+ UpdateDenom(subgraph, &relation_2_tdom);
142065
+ }
142066
+ auto remove_start = std::remove_if(subgraphs.begin(), subgraphs.end(),
142067
+ [](Subgraph2Denominator &s) { return s.relations.empty(); });
142068
+ subgraphs.erase(remove_start, subgraphs.end());
142069
+
142070
+ if (subgraphs.size() == 1 && subgraphs.at(0).relations.size() == new_set->count) {
142071
+ // You have found enough filters to connect the relations. These are guaranteed
142072
+ // to be the filters with the highest Tdoms.
142073
+ done = true;
142074
+ break;
142075
+ }
142076
+ }
142077
+ }
142078
+ double denom = 1;
142079
+ for (auto &match : subgraphs) {
142080
+ if (match.relations.size() == new_set->count) {
142081
+ denom = match.denom;
142082
+ }
142083
+ }
142084
+ // can happen if a table has cardinality 0, or a tdom is set to 0
142085
+ if (denom == 0) {
142086
+ denom = 1;
142087
+ }
142088
+ return numerator / denom;
142089
+ }
142090
+
142091
+ static bool IsLogicalFilter(LogicalOperator *op) {
142092
+ return op->type == LogicalOperatorType::LOGICAL_FILTER;
142093
+ }
142094
+
142095
+ static LogicalGet *GetLogicalGet(LogicalOperator *op) {
142096
+ LogicalGet *get = nullptr;
142097
+ switch (op->type) {
142098
+ case LogicalOperatorType::LOGICAL_GET:
142099
+ get = (LogicalGet *)op;
142100
+ break;
142101
+ case LogicalOperatorType::LOGICAL_FILTER:
142102
+ get = GetLogicalGet(op->children.at(0).get());
142103
+ break;
142104
+ case LogicalOperatorType::LOGICAL_PROJECTION:
142105
+ get = GetLogicalGet(op->children.at(0).get());
142106
+ break;
142107
+ case LogicalOperatorType::LOGICAL_COMPARISON_JOIN: {
142108
+ LogicalComparisonJoin *join = (LogicalComparisonJoin *)op;
142109
+ if (join->join_type == JoinType::MARK || join->join_type == JoinType::LEFT) {
142110
+ auto child = join->children.at(0).get();
142111
+ get = GetLogicalGet(child);
142112
+ }
142113
+ break;
142114
+ }
142115
+ default:
142116
+ // return null pointer, maybe there is no logical get under this child
142117
+ break;
142118
+ }
142119
+ return get;
142120
+ }
142121
+
142122
+ void CardinalityEstimator::MergeBindings(idx_t binding_index, idx_t relation_id,
142123
+ vector<column_binding_map_t<ColumnBinding>> &child_binding_maps) {
142124
+ for (auto &map_set : child_binding_maps) {
142125
+ for (auto &mapping : map_set) {
142126
+ ColumnBinding relation_bindings = mapping.first;
142127
+ ColumnBinding actual_bindings = mapping.second;
142128
+
142129
+ if (actual_bindings.table_index == binding_index) {
142130
+ auto key = ColumnBinding(relation_id, relation_bindings.column_index);
142131
+ AddRelationToColumnMapping(key, actual_bindings);
142132
+ }
142133
+ }
142134
+ }
142135
+ }
142136
+
142137
+ bool SortTdoms(const RelationsToTDom &a, const RelationsToTDom &b) {
142138
+ if (a.has_tdom_hll && b.has_tdom_hll) {
142139
+ return a.tdom_hll > b.tdom_hll;
142140
+ }
142141
+ if (a.has_tdom_hll) {
142142
+ return a.tdom_hll > b.tdom_no_hll;
142143
+ }
142144
+ if (b.has_tdom_hll) {
142145
+ return a.tdom_no_hll > b.tdom_hll;
142146
+ }
142147
+ return a.tdom_no_hll > b.tdom_no_hll;
142148
+ }
142149
+
142150
+ void CardinalityEstimator::InitCardinalityEstimatorProps(vector<struct NodeOp> *node_ops,
142151
+ vector<unique_ptr<FilterInfo>> *filter_infos) {
142152
+ InitEquivalentRelations(filter_infos);
142153
+ InitTotalDomains();
142154
+ for (idx_t i = 0; i < node_ops->size(); i++) {
142155
+ auto join_node = (*node_ops)[i].node.get();
142156
+ auto op = (*node_ops)[i].op;
142157
+ join_node->SetBaseTableCardinality(op->EstimateCardinality(context));
142158
+ if (op->type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN) {
142159
+ auto &join = (LogicalComparisonJoin &)*op;
142160
+ if (join.join_type == JoinType::LEFT) {
142161
+ // TODO: inspect child operators to get a more accurate cost
142162
+ // and cardinality estimation. If an base op is a Logical Comparison join
142163
+ // it is probably a left join, so cost of the larger table is a fine
142164
+ // estimate
142165
+ // No need to update a mark join cost because I say so.
142166
+ join_node->SetCost(join_node->GetBaseTableCardinality());
142167
+ }
142168
+ }
142169
+ // update cardinality with filters
142170
+ EstimateBaseTableCardinality(join_node, op);
142171
+ UpdateTotalDomains(join_node, op);
142172
+ }
142173
+
142174
+ // sort relations from greatest tdom to lowest tdom.
142175
+ std::sort(relations_to_tdoms.begin(), relations_to_tdoms.end(), SortTdoms);
142176
+ }
142177
+
142178
+ void CardinalityEstimator::UpdateTotalDomains(JoinNode *node, LogicalOperator *op) {
142179
+ auto relation_id = node->set->relations[0];
142180
+ relation_attributes[relation_id].cardinality = node->GetCardinality();
142181
+ TableCatalogEntry *catalog_table = nullptr;
142182
+ auto get = GetLogicalGet(op);
142183
+ if (get) {
142184
+ catalog_table = GetCatalogTableEntry(get);
142185
+ }
142186
+
142187
+ //! Initialize the tdoms for all columns the relation uses in join conditions.
142188
+ unordered_set<idx_t>::iterator ite;
142189
+ idx_t count = node->GetBaseTableCardinality();
142190
+
142191
+ bool direct_filter = false;
142192
+ for (auto &column : relation_attributes[relation_id].columns) {
142193
+ //! for every column in the relation, get the count via either HLL, or assume it to be
142194
+ //! the cardinality
142195
+ ColumnBinding key = ColumnBinding(relation_id, column);
142196
+
142197
+ if (catalog_table) {
142198
+ relation_attributes[relation_id].original_name = catalog_table->name;
142199
+ // Get HLL stats here
142200
+ auto actual_binding = relation_column_to_original_column[key];
142201
+
142202
+ // sometimes base stats is null (test_709.test) returns null for base stats while
142203
+ // there is still a catalog table. Anybody know anything about this?
142204
+ auto base_stats = catalog_table->storage->GetStatistics(context, actual_binding.column_index);
142205
+ if (base_stats) {
142206
+ count = base_stats->GetDistinctCount();
142207
+ }
142208
+
142209
+ // means you have a direct filter on a column. The count/total domain for the column
142210
+ // should be decreased to match the predicted total domain matching the filter.
142211
+ // We decrease the total domain for all columns in the equivalence set because filter pushdown
142212
+ // will mean all columns are affected.
142213
+ if (direct_filter) {
142214
+ count = node->GetCardinality();
142215
+ }
142216
+
142217
+ // HLL has estimation error, count can't be greater than cardinality of the table before filters
142218
+ if (count > node->GetBaseTableCardinality()) {
142219
+ count = node->GetBaseTableCardinality();
142220
+ }
142221
+ } else {
142222
+ // No HLL. So if we know there is a direct filter, reduce count to cardinality with filter
142223
+ // otherwise assume the total domain is still the cardinality
142224
+ if (direct_filter) {
142225
+ count = node->GetCardinality();
142226
+ } else {
142227
+ count = node->GetBaseTableCardinality();
142228
+ }
142229
+ }
142230
+
142231
+ for (auto &relation_to_tdom : relations_to_tdoms) {
142232
+ column_binding_set_t i_set = relation_to_tdom.equivalent_relations;
142233
+ if (i_set.count(key) != 1) {
142234
+ continue;
142235
+ }
142236
+ if (catalog_table) {
142237
+ if (relation_to_tdom.tdom_hll < count) {
142238
+ relation_to_tdom.tdom_hll = count;
142239
+ relation_to_tdom.has_tdom_hll = true;
142240
+ }
142241
+ if (relation_to_tdom.tdom_no_hll > count) {
142242
+ relation_to_tdom.tdom_no_hll = count;
142243
+ }
142244
+ } else {
142245
+ // Here we don't have catalog statistics, and the following is how we determine
142246
+ // the tdom
142247
+ // 1. If there is any hll data in the equivalence set, use that
142248
+ // 2. Otherwise, use the table with the smallest cardinality
142249
+ if (relation_to_tdom.tdom_no_hll > count && !relation_to_tdom.has_tdom_hll) {
142250
+ relation_to_tdom.tdom_no_hll = count;
142251
+ }
142252
+ }
142253
+ break;
142254
+ }
142255
+ }
142256
+ }
142257
+
142258
+ TableFilterSet *CardinalityEstimator::GetTableFilters(LogicalOperator *op) {
142259
+ // First check table filters
142260
+ auto get = GetLogicalGet(op);
142261
+ return get ? &get->table_filters : nullptr;
142262
+ }
142263
+
142264
+ idx_t CardinalityEstimator::InspectConjunctionAND(idx_t cardinality, idx_t column_index, ConjunctionAndFilter *filter,
142265
+ unique_ptr<BaseStatistics> base_stats) {
142266
+ auto has_equality_filter = false;
142267
+ auto cardinality_after_filters = cardinality;
142268
+ for (auto &child_filter : filter->child_filters) {
142269
+ if (child_filter->filter_type != TableFilterType::CONSTANT_COMPARISON) {
142270
+ continue;
142271
+ }
142272
+ auto comparison_filter = (ConstantFilter &)*child_filter;
142273
+ if (comparison_filter.comparison_type != ExpressionType::COMPARE_EQUAL) {
142274
+ continue;
142275
+ }
142276
+ auto column_count = 0;
142277
+ if (base_stats) {
142278
+ column_count = base_stats->GetDistinctCount();
142279
+ }
142280
+ auto filtered_card = cardinality;
142281
+ // column_count = 0 when there is no column count (i.e parquet scans)
142282
+ if (column_count > 0) {
142283
+ // we want the ceil of cardinality/column_count. We also want to avoid compiler errors
142284
+ filtered_card = (cardinality + column_count - 1) / column_count;
142285
+ cardinality_after_filters = filtered_card;
142286
+ }
142287
+ if (has_equality_filter) {
142288
+ cardinality_after_filters = MinValue(filtered_card, cardinality_after_filters);
142289
+ }
142290
+ has_equality_filter = true;
142291
+ }
142292
+ return cardinality_after_filters;
142293
+ }
142294
+
142295
+ idx_t CardinalityEstimator::InspectConjunctionOR(idx_t cardinality, idx_t column_index, ConjunctionOrFilter *filter,
142296
+ unique_ptr<BaseStatistics> base_stats) {
142297
+ auto has_equality_filter = false;
142298
+ auto cardinality_after_filters = cardinality;
142299
+ for (auto &child_filter : filter->child_filters) {
142300
+ if (child_filter->filter_type != TableFilterType::CONSTANT_COMPARISON) {
142301
+ continue;
142302
+ }
142303
+ auto comparison_filter = (ConstantFilter &)*child_filter;
142304
+ if (comparison_filter.comparison_type == ExpressionType::COMPARE_EQUAL) {
142305
+ auto column_count = cardinality_after_filters;
142306
+ if (base_stats) {
142307
+ column_count = base_stats->GetDistinctCount();
142308
+ }
142309
+ auto increment = MaxValue<idx_t>(((cardinality + column_count - 1) / column_count), 1);
142310
+ if (has_equality_filter) {
142311
+ cardinality_after_filters += increment;
142312
+ } else {
142313
+ cardinality_after_filters = increment;
142314
+ }
142315
+ has_equality_filter = true;
142316
+ }
142317
+ }
142318
+ D_ASSERT(cardinality_after_filters > 0);
142319
+ return cardinality_after_filters;
142320
+ }
142321
+
142322
+ idx_t CardinalityEstimator::InspectTableFilters(idx_t cardinality, LogicalOperator *op, TableFilterSet *table_filters) {
142323
+ idx_t cardinality_after_filters = cardinality;
142324
+ auto get = GetLogicalGet(op);
142325
+ unique_ptr<BaseStatistics> column_statistics;
142326
+ for (auto &it : table_filters->filters) {
142327
+ column_statistics = nullptr;
142328
+ if (get->bind_data && get->function.name.compare("seq_scan") == 0) {
142329
+ auto &table_scan_bind_data = (TableScanBindData &)*get->bind_data;
142330
+ column_statistics = get->function.statistics(context, &table_scan_bind_data, it.first);
142331
+ }
142332
+ if (it.second->filter_type == TableFilterType::CONJUNCTION_AND) {
142333
+ auto &filter = (ConjunctionAndFilter &)*it.second;
142334
+ idx_t cardinality_with_and_filter =
142335
+ InspectConjunctionAND(cardinality, it.first, &filter, move(column_statistics));
142336
+ cardinality_after_filters = MinValue(cardinality_after_filters, cardinality_with_and_filter);
142337
+ } else if (it.second->filter_type == TableFilterType::CONJUNCTION_OR) {
142338
+ auto &filter = (ConjunctionOrFilter &)*it.second;
142339
+ idx_t cardinality_with_or_filter =
142340
+ InspectConjunctionOR(cardinality, it.first, &filter, move(column_statistics));
142341
+ cardinality_after_filters = MinValue(cardinality_after_filters, cardinality_with_or_filter);
142342
+ }
142343
+ }
142344
+ // if the above code didn't find an equality filter (i.e country_code = "[us]")
142345
+ // and there are other table filters, use default selectivity.
142346
+ bool has_equality_filter = (cardinality_after_filters != cardinality);
142347
+ if (!has_equality_filter && !table_filters->filters.empty()) {
142348
+ cardinality_after_filters = MaxValue<idx_t>(cardinality * DEFAULT_SELECTIVITY, 1);
142349
+ }
142350
+ return cardinality_after_filters;
142351
+ }
142352
+
142353
+ void CardinalityEstimator::EstimateBaseTableCardinality(JoinNode *node, LogicalOperator *op) {
142354
+ auto has_logical_filter = IsLogicalFilter(op);
142355
+ auto table_filters = GetTableFilters(op);
142356
+
142357
+ auto card_after_filters = node->GetBaseTableCardinality();
142358
+ // Logical Filter on a seq scan
142359
+ if (has_logical_filter) {
142360
+ card_after_filters *= DEFAULT_SELECTIVITY;
142361
+ } else if (table_filters) {
142362
+ double inspect_result = (double)InspectTableFilters(card_after_filters, op, table_filters);
142363
+ card_after_filters = MinValue(inspect_result, (double)card_after_filters);
142364
+ }
142365
+ node->SetEstimatedCardinality(card_after_filters);
142366
+ }
142367
+
141715
142368
  } // namespace duckdb
141716
142369
  //===----------------------------------------------------------------------===//
141717
142370
  // DuckDB
@@ -142465,6 +143118,27 @@ bool Deliminator::RemoveCandidate(unique_ptr<LogicalOperator> *op_ptr, Deliminat
142465
143118
  }
142466
143119
 
142467
143120
  } // namespace duckdb
143121
+
143122
+
143123
+
143124
+ namespace duckdb {
143125
+
143126
+ double EstimatedProperties::GetCardinality() {
143127
+ return cardinality;
143128
+ }
143129
+ double EstimatedProperties::GetCost() {
143130
+ return cost;
143131
+ }
143132
+
143133
+ void EstimatedProperties::SetCardinality(double new_card) {
143134
+ cardinality = new_card;
143135
+ }
143136
+
143137
+ void EstimatedProperties::SetCost(double new_cost) {
143138
+ cost = new_cost;
143139
+ }
143140
+
143141
+ } // namespace duckdb
142468
143142
  //===----------------------------------------------------------------------===//
142469
143143
  // DuckDB
142470
143144
  //
@@ -144528,13 +145202,44 @@ unique_ptr<Expression> InClauseRewriter::VisitReplace(BoundOperatorExpression &e
144528
145202
  }
144529
145203
 
144530
145204
  } // namespace duckdb
144531
- //===----------------------------------------------------------------------===//
144532
- // DuckDB
144533
- //
144534
- // duckdb/optimizer/join_order/join_relation.hpp
144535
- //
144536
- //
144537
- //===----------------------------------------------------------------------===//
145205
+
145206
+
145207
+
145208
+
145209
+
145210
+
145211
+
145212
+
145213
+
145214
+
145215
+
145216
+
145217
+
145218
+
145219
+
145220
+
145221
+
145222
+
145223
+
145224
+
145225
+
145226
+
145227
+
145228
+
145229
+
145230
+
145231
+
145232
+
145233
+
145234
+
145235
+
145236
+
145237
+
145238
+
145239
+
145240
+
145241
+
145242
+
144538
145243
 
144539
145244
 
144540
145245
 
@@ -144543,59 +145248,73 @@ unique_ptr<Expression> InClauseRewriter::VisitReplace(BoundOperatorExpression &e
144543
145248
 
144544
145249
 
144545
145250
  namespace duckdb {
144546
- class LogicalOperator;
144547
145251
 
144548
- //! Represents a single relation and any metadata accompanying that relation
144549
- struct SingleJoinRelation {
144550
- LogicalOperator *op;
144551
- LogicalOperator *parent;
145252
+ JoinNode::JoinNode(JoinRelationSet *set, const double base_cardinality)
145253
+ : set(set), info(nullptr), has_filter(false), left(nullptr), right(nullptr), base_cardinality(base_cardinality) {
145254
+ estimated_props = make_unique<EstimatedProperties>(base_cardinality, 0);
145255
+ }
144552
145256
 
144553
- SingleJoinRelation() {
144554
- }
144555
- SingleJoinRelation(LogicalOperator *op, LogicalOperator *parent) : op(op), parent(parent) {
144556
- }
144557
- };
145257
+ JoinNode::JoinNode(JoinRelationSet *set, NeighborInfo *info, JoinNode *left, JoinNode *right,
145258
+ const double base_cardinality, double cost)
145259
+ : set(set), info(info), has_filter(false), left(left), right(right), base_cardinality(base_cardinality) {
145260
+ estimated_props = make_unique<EstimatedProperties>(base_cardinality, cost);
145261
+ }
144558
145262
 
144559
- //! Set of relations, used in the join graph.
144560
- struct JoinRelationSet {
144561
- JoinRelationSet(unique_ptr<idx_t[]> relations, idx_t count) : relations(move(relations)), count(count) {
144562
- }
145263
+ unique_ptr<EstimatedProperties> EstimatedProperties::Copy() {
145264
+ auto result = make_unique<EstimatedProperties>(cardinality, cost);
145265
+ return result;
145266
+ }
144563
145267
 
144564
- string ToString() const;
145268
+ double JoinNode::GetCardinality() const {
145269
+ return estimated_props->GetCardinality();
145270
+ }
144565
145271
 
144566
- unique_ptr<idx_t[]> relations;
144567
- idx_t count;
145272
+ double JoinNode::GetCost() {
145273
+ return estimated_props->GetCost();
145274
+ }
144568
145275
 
144569
- static bool IsSubset(JoinRelationSet *super, JoinRelationSet *sub);
144570
- };
145276
+ void JoinNode::SetCost(double cost) {
145277
+ estimated_props->SetCost(cost);
145278
+ }
144571
145279
 
144572
- //! The JoinRelationTree is a structure holding all the created JoinRelationSet objects and allowing fast lookup on to
144573
- //! them
144574
- class JoinRelationSetManager {
144575
- public:
144576
- //! Contains a node with a JoinRelationSet and child relations
144577
- // FIXME: this structure is inefficient, could use a bitmap for lookup instead (todo: profile)
144578
- struct JoinRelationTreeNode {
144579
- unique_ptr<JoinRelationSet> relation;
144580
- unordered_map<idx_t, unique_ptr<JoinRelationTreeNode>> children;
144581
- };
145280
+ double JoinNode::GetBaseTableCardinality() {
145281
+ if (set->count > 1) {
145282
+ throw InvalidInputException("Cannot call get base table cardinality on intermediate join node");
145283
+ }
145284
+ return base_cardinality;
145285
+ }
144582
145286
 
144583
- public:
144584
- //! Create or get a JoinRelationSet from a single node with the given index
144585
- JoinRelationSet *GetJoinRelation(idx_t index);
144586
- //! Create or get a JoinRelationSet from a set of relation bindings
144587
- JoinRelationSet *GetJoinRelation(unordered_set<idx_t> &bindings);
144588
- //! Create or get a JoinRelationSet from a (sorted, duplicate-free!) list of relations
144589
- JoinRelationSet *GetJoinRelation(unique_ptr<idx_t[]> relations, idx_t count);
144590
- //! Union two sets of relations together and create a new relation set
144591
- JoinRelationSet *Union(JoinRelationSet *left, JoinRelationSet *right);
144592
- // //! Create the set difference of left \ right (i.e. all elements in left that are not in right)
144593
- // JoinRelationSet *Difference(JoinRelationSet *left, JoinRelationSet *right);
145287
+ void JoinNode::SetBaseTableCardinality(double base_card) {
145288
+ base_cardinality = base_card;
145289
+ }
144594
145290
 
144595
- private:
144596
- JoinRelationTreeNode root;
144597
- };
145291
+ void JoinNode::SetEstimatedCardinality(double estimated_card) {
145292
+ estimated_props->SetCardinality(estimated_card);
145293
+ }
144598
145294
 
145295
+ string JoinNode::ToString() {
145296
+ if (!set) {
145297
+ return "";
145298
+ }
145299
+ string result = "-------------------------------\n";
145300
+ result += set->ToString() + "\n";
145301
+ result += "card = " + to_string(GetCardinality()) + "\n";
145302
+ bool is_cartesian = false;
145303
+ if (left && right) {
145304
+ is_cartesian = (GetCardinality() == left->GetCardinality() * right->GetCardinality());
145305
+ }
145306
+ result += "cartesian = " + to_string(is_cartesian) + "\n";
145307
+ result += "cost = " + to_string(estimated_props->GetCost()) + "\n";
145308
+ result += "left = \n";
145309
+ if (left) {
145310
+ result += left->ToString();
145311
+ }
145312
+ result += "right = \n";
145313
+ if (right) {
145314
+ result += right->ToString();
145315
+ }
145316
+ return result;
145317
+ }
144599
145318
  } // namespace duckdb
144600
145319
 
144601
145320
 
@@ -144743,76 +145462,6 @@ JoinRelationSet *JoinRelationSetManager::Union(JoinRelationSet *left, JoinRelati
144743
145462
  // }
144744
145463
 
144745
145464
  } // namespace duckdb
144746
- //===----------------------------------------------------------------------===//
144747
- // DuckDB
144748
- //
144749
- // duckdb/optimizer/join_order/query_graph.hpp
144750
- //
144751
- //
144752
- //===----------------------------------------------------------------------===//
144753
-
144754
-
144755
-
144756
-
144757
-
144758
-
144759
-
144760
-
144761
-
144762
- #include <functional>
144763
-
144764
- namespace duckdb {
144765
- class Expression;
144766
- class LogicalOperator;
144767
-
144768
- struct FilterInfo {
144769
- idx_t filter_index;
144770
- JoinRelationSet *left_set = nullptr;
144771
- JoinRelationSet *right_set = nullptr;
144772
- JoinRelationSet *set = nullptr;
144773
- };
144774
-
144775
- struct FilterNode {
144776
- vector<FilterInfo *> filters;
144777
- unordered_map<idx_t, unique_ptr<FilterNode>> children;
144778
- };
144779
-
144780
- struct NeighborInfo {
144781
- JoinRelationSet *neighbor;
144782
- vector<FilterInfo *> filters;
144783
- };
144784
-
144785
- //! The QueryGraph contains edges between relations and allows edges to be created/queried
144786
- class QueryGraph {
144787
- public:
144788
- //! Contains a node with info about neighboring relations and child edge infos
144789
- struct QueryEdge {
144790
- vector<unique_ptr<NeighborInfo>> neighbors;
144791
- unordered_map<idx_t, unique_ptr<QueryEdge>> children;
144792
- };
144793
-
144794
- public:
144795
- string ToString() const;
144796
- void Print();
144797
-
144798
- //! Create an edge in the edge_set
144799
- void CreateEdge(JoinRelationSet *left, JoinRelationSet *right, FilterInfo *info);
144800
- //! Returns a connection if there is an edge that connects these two sets, or nullptr otherwise
144801
- NeighborInfo *GetConnection(JoinRelationSet *node, JoinRelationSet *other);
144802
- //! Enumerate the neighbors of a specific node that do not belong to any of the exclusion_set. Note that if a
144803
- //! neighbor has multiple nodes, this function will return the lowest entry in that set.
144804
- vector<idx_t> GetNeighbors(JoinRelationSet *node, unordered_set<idx_t> &exclusion_set);
144805
- //! Enumerate all neighbors of a given JoinRelationSet node
144806
- void EnumerateNeighbors(JoinRelationSet *node, const std::function<bool(NeighborInfo *)> &callback);
144807
-
144808
- private:
144809
- //! Get the QueryEdge of a specific node
144810
- QueryEdge *GetQueryEdge(JoinRelationSet *left);
144811
-
144812
- QueryEdge root;
144813
- };
144814
-
144815
- } // namespace duckdb
144816
145465
 
144817
145466
 
144818
145467
 
@@ -144931,30 +145580,18 @@ vector<idx_t> QueryGraph::GetNeighbors(JoinRelationSet *node, unordered_set<idx_
144931
145580
  return neighbors;
144932
145581
  }
144933
145582
 
144934
- NeighborInfo *QueryGraph::GetConnection(JoinRelationSet *node, JoinRelationSet *other) {
144935
- NeighborInfo *connection = nullptr;
145583
+ vector<NeighborInfo *> QueryGraph::GetConnections(JoinRelationSet *node, JoinRelationSet *other) {
145584
+ vector<NeighborInfo *> connections;
144936
145585
  EnumerateNeighbors(node, [&](NeighborInfo *info) -> bool {
144937
145586
  if (JoinRelationSet::IsSubset(other, info->neighbor)) {
144938
- connection = info;
144939
- return true;
145587
+ connections.push_back(info);
144940
145588
  }
144941
145589
  return false;
144942
145590
  });
144943
- return connection;
145591
+ return connections;
144944
145592
  }
144945
145593
 
144946
145594
  } // namespace duckdb
144947
- //===----------------------------------------------------------------------===//
144948
- // DuckDB
144949
- //
144950
- // duckdb/optimizer/join_order_optimizer.hpp
144951
- //
144952
- //
144953
- //===----------------------------------------------------------------------===//
144954
-
144955
-
144956
-
144957
-
144958
145595
 
144959
145596
 
144960
145597
 
@@ -144962,152 +145599,22 @@ NeighborInfo *QueryGraph::GetConnection(JoinRelationSet *node, JoinRelationSet *
144962
145599
 
144963
145600
 
144964
145601
 
144965
- #include <functional>
144966
-
144967
- namespace duckdb {
144968
145602
 
144969
- class JoinOrderOptimizer {
144970
- public:
144971
- //! Represents a node in the join plan
144972
- struct JoinNode {
144973
- JoinRelationSet *set;
144974
- NeighborInfo *info;
144975
- idx_t cardinality;
144976
- idx_t cost;
144977
- JoinNode *left;
144978
- JoinNode *right;
145603
+ #include <algorithm>
144979
145604
 
144980
- //! Create a leaf node in the join tree
144981
- JoinNode(JoinRelationSet *set, idx_t cardinality)
144982
- : set(set), info(nullptr), cardinality(cardinality), cost(cardinality), left(nullptr), right(nullptr) {
144983
- }
144984
- //! Create an intermediate node in the join tree
144985
- JoinNode(JoinRelationSet *set, NeighborInfo *info, JoinNode *left, JoinNode *right, idx_t cardinality,
144986
- idx_t cost)
144987
- : set(set), info(info), cardinality(cardinality), cost(cost), left(left), right(right) {
144988
- }
144989
- };
145605
+ namespace std {
144990
145606
 
144991
- public:
144992
- explicit JoinOrderOptimizer(ClientContext &context) : context(context) {
145607
+ //! A JoinNode is defined by the relations it joins.
145608
+ template <>
145609
+ struct hash<duckdb::JoinNode> {
145610
+ inline string operator()(const duckdb::JoinNode &join_node) const {
145611
+ return join_node.set->ToString();
144993
145612
  }
144994
-
144995
- //! Perform join reordering inside a plan
144996
- unique_ptr<LogicalOperator> Optimize(unique_ptr<LogicalOperator> plan);
144997
-
144998
- private:
144999
- ClientContext &context;
145000
- //! The total amount of join pairs that have been considered
145001
- idx_t pairs = 0;
145002
- //! Set of all relations considered in the join optimizer
145003
- vector<unique_ptr<SingleJoinRelation>> relations;
145004
- //! A mapping of base table index -> index into relations array (relation number)
145005
- unordered_map<idx_t, idx_t> relation_mapping;
145006
- //! A structure holding all the created JoinRelationSet objects
145007
- JoinRelationSetManager set_manager;
145008
- //! The set of edges used in the join optimizer
145009
- QueryGraph query_graph;
145010
- //! The optimal join plan found for the specific JoinRelationSet*
145011
- unordered_map<JoinRelationSet *, unique_ptr<JoinNode>> plans;
145012
- //! The set of filters extracted from the query graph
145013
- vector<unique_ptr<Expression>> filters;
145014
- //! The set of filter infos created from the extracted filters
145015
- vector<unique_ptr<FilterInfo>> filter_infos;
145016
- //! A map of all expressions a given expression has to be equivalent to. This is used to add "implied join edges".
145017
- //! i.e. in the join A=B AND B=C, the equivalence set of {B} is {A, C}, thus we can add an implied join edge {A <->
145018
- //! C}
145019
- expression_map_t<vector<FilterInfo *>> equivalence_sets;
145020
-
145021
- //! Extract the bindings referred to by an Expression
145022
- bool ExtractBindings(Expression &expression, unordered_set<idx_t> &bindings);
145023
- //! Traverse the query tree to find (1) base relations, (2) existing join conditions and (3) filters that can be
145024
- //! rewritten into joins. Returns true if there are joins in the tree that can be reordered, false otherwise.
145025
- bool ExtractJoinRelations(LogicalOperator &input_op, vector<LogicalOperator *> &filter_operators,
145026
- LogicalOperator *parent = nullptr);
145027
- //! Emit a pair as a potential join candidate. Returns the best plan found for the (left, right) connection (either
145028
- //! the newly created plan, or an existing plan)
145029
- JoinNode *EmitPair(JoinRelationSet *left, JoinRelationSet *right, NeighborInfo *info);
145030
- //! Tries to emit a potential join candidate pair. Returns false if too many pairs have already been emitted,
145031
- //! cancelling the dynamic programming step.
145032
- bool TryEmitPair(JoinRelationSet *left, JoinRelationSet *right, NeighborInfo *info);
145033
-
145034
- bool EnumerateCmpRecursive(JoinRelationSet *left, JoinRelationSet *right, unordered_set<idx_t> exclusion_set);
145035
- //! Emit a relation set node
145036
- bool EmitCSG(JoinRelationSet *node);
145037
- //! Enumerate the possible connected subgraphs that can be joined together in the join graph
145038
- bool EnumerateCSGRecursive(JoinRelationSet *node, unordered_set<idx_t> &exclusion_set);
145039
- //! Rewrite a logical query plan given the join plan
145040
- unique_ptr<LogicalOperator> RewritePlan(unique_ptr<LogicalOperator> plan, JoinNode *node);
145041
- //! Generate cross product edges inside the side
145042
- void GenerateCrossProducts();
145043
- //! Perform the join order solving
145044
- void SolveJoinOrder();
145045
- //! Solve the join order exactly using dynamic programming. Returns true if it was completed successfully (i.e. did
145046
- //! not time-out)
145047
- bool SolveJoinOrderExactly();
145048
- //! Solve the join order approximately using a greedy algorithm
145049
- void SolveJoinOrderApproximately();
145050
-
145051
- unique_ptr<LogicalOperator> ResolveJoinConditions(unique_ptr<LogicalOperator> op);
145052
- std::pair<JoinRelationSet *, unique_ptr<LogicalOperator>>
145053
- GenerateJoins(vector<unique_ptr<LogicalOperator>> &extracted_relations, JoinNode *node);
145054
145613
  };
145055
-
145056
- } // namespace duckdb
145057
-
145058
-
145059
-
145060
-
145061
-
145062
-
145063
-
145064
-
145065
-
145066
-
145067
-
145068
-
145069
-
145070
-
145071
-
145072
-
145073
-
145074
-
145075
-
145076
-
145077
-
145078
-
145079
-
145080
-
145081
-
145082
-
145083
-
145084
-
145085
-
145086
-
145087
-
145088
-
145089
-
145090
-
145091
-
145092
-
145093
-
145094
-
145095
-
145096
-
145097
-
145098
-
145099
-
145100
-
145101
-
145102
-
145103
-
145104
-
145105
- #include <algorithm>
145614
+ } // namespace std
145106
145615
 
145107
145616
  namespace duckdb {
145108
145617
 
145109
- using JoinNode = JoinOrderOptimizer::JoinNode;
145110
-
145111
145618
  //! Returns true if A and B are disjoint, false otherwise
145112
145619
  template <class T>
145113
145620
  static bool Disjoint(unordered_set<T> &a, unordered_set<T> &b) {
@@ -145127,6 +145634,9 @@ bool JoinOrderOptimizer::ExtractBindings(Expression &expression, unordered_set<i
145127
145634
  D_ASSERT(colref.binding.table_index != DConstants::INVALID_INDEX);
145128
145635
  // map the base table index to the relation index used by the JoinOrderOptimizer
145129
145636
  D_ASSERT(relation_mapping.find(colref.binding.table_index) != relation_mapping.end());
145637
+ auto catalog_table = relation_mapping[colref.binding.table_index];
145638
+ auto column_index = colref.binding.column_index;
145639
+ cardinality_estimator.AddColumnToRelationMap(catalog_table, column_index);
145130
145640
  bindings.insert(relation_mapping[colref.binding.table_index]);
145131
145641
  }
145132
145642
  if (expression.type == ExpressionType::BOUND_REF) {
@@ -145145,6 +145655,39 @@ bool JoinOrderOptimizer::ExtractBindings(Expression &expression, unordered_set<i
145145
145655
  return can_reorder;
145146
145656
  }
145147
145657
 
145658
+ void JoinOrderOptimizer::GetColumnBindings(Expression &expression, ColumnBinding &left_binding,
145659
+ ColumnBinding &right_binding) {
145660
+ if (expression.type == ExpressionType::COMPARE_EQUAL) {
145661
+ auto &colref = (BoundComparisonExpression &)expression;
145662
+ if (colref.right->type == ExpressionType::BOUND_COLUMN_REF &&
145663
+ colref.left->type == ExpressionType::BOUND_COLUMN_REF) {
145664
+ auto &right = (BoundColumnRefExpression &)*colref.right;
145665
+ auto &left = (BoundColumnRefExpression &)*colref.left;
145666
+ D_ASSERT(relation_mapping.find(left.binding.table_index) != relation_mapping.end());
145667
+ D_ASSERT(relation_mapping.find(right.binding.table_index) != relation_mapping.end());
145668
+ left_binding = ColumnBinding(relation_mapping[left.binding.table_index], left.binding.column_index);
145669
+ right_binding = ColumnBinding(relation_mapping[right.binding.table_index], right.binding.column_index);
145670
+ return;
145671
+ }
145672
+ } else if (expression.type == ExpressionType::BOUND_COLUMN_REF) {
145673
+ // Here you have a filter on a single column in a table. Return a binding for the column
145674
+ // being filtered on so the filter estimator knows what HLL count to pull
145675
+ auto &colref = (BoundColumnRefExpression &)expression;
145676
+ D_ASSERT(colref.depth == 0);
145677
+ D_ASSERT(colref.binding.table_index != DConstants::INVALID_INDEX);
145678
+ // map the base table index to the relation index used by the JoinOrderOptimizer
145679
+ D_ASSERT(relation_mapping.find(colref.binding.table_index) != relation_mapping.end());
145680
+ left_binding = ColumnBinding(relation_mapping[colref.binding.table_index], colref.binding.column_index);
145681
+ return;
145682
+ }
145683
+ // TODO: handle inequality filters with functions.
145684
+ // TODO: Don't overwrite the right binding. This fails silently right now
145685
+ // When enumerating the children, it's possible you overwrite the left_binding
145686
+ // if the right child is an expression with more children than the left child.
145687
+ ExpressionIterator::EnumerateChildren(
145688
+ expression, [&](Expression &expr) { GetColumnBindings(expr, left_binding, right_binding); });
145689
+ }
145690
+
145148
145691
  static unique_ptr<LogicalOperator> PushFilter(unique_ptr<LogicalOperator> node, unique_ptr<Expression> expr) {
145149
145692
  // push an expression into a filter
145150
145693
  // first check if we have any filter to push it into
@@ -145220,9 +145763,18 @@ bool JoinOrderOptimizer::ExtractJoinRelations(LogicalOperator &input_op, vector<
145220
145763
  // e.g. suppose we have (left LEFT OUTER JOIN right WHERE right IS NOT NULL), the join can generate
145221
145764
  // new NULL values in the right side, so pushing this condition through the join leads to incorrect results
145222
145765
  // for this reason, we just start a new JoinOptimizer pass in each of the children of the join
145766
+
145767
+ // Keep track of all of the filter bindings the new join order optimizer makes
145768
+ vector<column_binding_map_t<ColumnBinding>> child_binding_maps;
145769
+ idx_t child_bindings_it = 0;
145223
145770
  for (auto &child : op->children) {
145771
+ child_binding_maps.emplace_back(column_binding_map_t<ColumnBinding>());
145224
145772
  JoinOrderOptimizer optimizer(context);
145225
145773
  child = optimizer.Optimize(move(child));
145774
+ // save the relation bindings from the optimized child. These later all get added to the
145775
+ // parent cardinality_estimator relation column binding map.
145776
+ optimizer.cardinality_estimator.CopyRelationMap(child_binding_maps.at(child_bindings_it));
145777
+ child_bindings_it += 1;
145226
145778
  }
145227
145779
  // after this we want to treat this node as one "end node" (like e.g. a base relation)
145228
145780
  // however the join refers to multiple base relations
@@ -145233,8 +145785,11 @@ bool JoinOrderOptimizer::ExtractJoinRelations(LogicalOperator &input_op, vector<
145233
145785
  LogicalJoin::GetTableReferences(*op, bindings);
145234
145786
  // now create the relation that refers to all these bindings
145235
145787
  auto relation = make_unique<SingleJoinRelation>(&input_op, parent);
145788
+ auto relation_id = relations.size();
145789
+ // Add binding information from the nonreorderable join to this relation.
145236
145790
  for (idx_t it : bindings) {
145237
- relation_mapping[it] = relations.size();
145791
+ cardinality_estimator.MergeBindings(it, relation_id, child_binding_maps);
145792
+ relation_mapping[it] = relation_id;
145238
145793
  }
145239
145794
  relations.push_back(move(relation));
145240
145795
  return true;
@@ -145249,14 +145804,21 @@ bool JoinOrderOptimizer::ExtractJoinRelations(LogicalOperator &input_op, vector<
145249
145804
  // base table scan, add to set of relations
145250
145805
  auto get = (LogicalGet *)op;
145251
145806
  auto relation = make_unique<SingleJoinRelation>(&input_op, parent);
145252
- relation_mapping[get->table_index] = relations.size();
145807
+ idx_t relation_id = relations.size();
145808
+ //! make sure the optimizer has knowledge of the exact column bindings as well.
145809
+ auto table_index = get->table_index;
145810
+ relation_mapping[table_index] = relation_id;
145811
+ cardinality_estimator.AddRelationColumnMapping(get, relation_id);
145253
145812
  relations.push_back(move(relation));
145254
145813
  return true;
145255
145814
  } else if (op->type == LogicalOperatorType::LOGICAL_EXPRESSION_GET) {
145256
145815
  // base table scan, add to set of relations
145257
145816
  auto get = (LogicalExpressionGet *)op;
145258
145817
  auto relation = make_unique<SingleJoinRelation>(&input_op, parent);
145259
- relation_mapping[get->table_index] = relations.size();
145818
+ idx_t relation_id = relations.size();
145819
+ //! make sure the optimizer has knowledge of the exact column bindings as well.
145820
+ auto table_index = get->table_index;
145821
+ relation_mapping[table_index] = relation_id;
145260
145822
  relations.push_back(move(relation));
145261
145823
  return true;
145262
145824
  } else if (op->type == LogicalOperatorType::LOGICAL_DUMMY_SCAN) {
@@ -145288,31 +145850,55 @@ static void UpdateExclusionSet(JoinRelationSet *node, unordered_set<idx_t> &excl
145288
145850
  }
145289
145851
 
145290
145852
  //! Create a new JoinTree node by joining together two previous JoinTree nodes
145291
- static unique_ptr<JoinNode> CreateJoinTree(JoinRelationSet *set, NeighborInfo *info, JoinNode *left, JoinNode *right) {
145853
+ unique_ptr<JoinNode> JoinOrderOptimizer::CreateJoinTree(JoinRelationSet *set,
145854
+ const vector<NeighborInfo *> &possible_connections,
145855
+ JoinNode *left, JoinNode *right) {
145292
145856
  // for the hash join we want the right side (build side) to have the smallest cardinality
145293
145857
  // also just a heuristic but for now...
145294
145858
  // FIXME: we should probably actually benchmark that as well
145295
145859
  // FIXME: should consider different join algorithms, should we pick a join algorithm here as well? (probably)
145296
- if (left->cardinality < right->cardinality) {
145297
- return CreateJoinTree(set, info, right, left);
145298
- }
145299
- // the expected cardinality is the max of the child cardinalities
145300
- // FIXME: we should obviously use better cardinality estimation here
145301
- // but for now we just assume foreign key joins only
145302
- idx_t expected_cardinality;
145303
- if (info->filters.empty()) {
145860
+ double expected_cardinality;
145861
+ NeighborInfo *best_connection = nullptr;
145862
+ auto plan = plans.find(set);
145863
+ // if we have already calculated an expected cardinality for this set,
145864
+ // just re-use that cardinality
145865
+ if (left->GetCardinality() < right->GetCardinality()) {
145866
+ return CreateJoinTree(set, possible_connections, right, left);
145867
+ }
145868
+ if (plan != plans.end()) {
145869
+ expected_cardinality = plan->second->GetCardinality();
145870
+ best_connection = possible_connections.back();
145871
+ } else if (possible_connections.empty()) {
145304
145872
  // cross product
145305
- expected_cardinality = left->cardinality * right->cardinality;
145873
+ expected_cardinality = cardinality_estimator.EstimateCrossProduct(left, right);
145306
145874
  } else {
145307
145875
  // normal join, expect foreign key join
145308
- expected_cardinality = MaxValue(left->cardinality, right->cardinality);
145876
+ expected_cardinality = cardinality_estimator.EstimateCardinalityWithSet(set);
145877
+ best_connection = possible_connections.back();
145309
145878
  }
145310
- // cost is expected_cardinality plus the cost of the previous plans
145311
- idx_t cost = expected_cardinality;
145312
- return make_unique<JoinNode>(set, info, left, right, expected_cardinality, cost);
145879
+
145880
+ auto cost = CardinalityEstimator::ComputeCost(left, right, expected_cardinality);
145881
+ auto result = make_unique<JoinNode>(set, best_connection, left, right, expected_cardinality, cost);
145882
+ D_ASSERT(cost >= expected_cardinality);
145883
+ return result;
145313
145884
  }
145314
145885
 
145315
- JoinNode *JoinOrderOptimizer::EmitPair(JoinRelationSet *left, JoinRelationSet *right, NeighborInfo *info) {
145886
+ void JoinOrderOptimizer::UpdateJoinNodesInFullPlan(JoinNode *node) {
145887
+ if (!node) {
145888
+ return;
145889
+ }
145890
+ if (node->set->count == relations.size()) {
145891
+ join_nodes_in_full_plan.clear();
145892
+ }
145893
+ if (node->set->count < relations.size()) {
145894
+ join_nodes_in_full_plan.insert(node);
145895
+ }
145896
+ UpdateJoinNodesInFullPlan(node->left);
145897
+ UpdateJoinNodesInFullPlan(node->right);
145898
+ }
145899
+
145900
+ JoinNode *JoinOrderOptimizer::EmitPair(JoinRelationSet *left, JoinRelationSet *right,
145901
+ const vector<NeighborInfo *> &info) {
145316
145902
  // get the left and right join plans
145317
145903
  auto &left_plan = plans[left];
145318
145904
  auto &right_plan = plans[right];
@@ -145321,18 +145907,45 @@ JoinNode *JoinOrderOptimizer::EmitPair(JoinRelationSet *left, JoinRelationSet *r
145321
145907
  auto new_plan = CreateJoinTree(new_set, info, left_plan.get(), right_plan.get());
145322
145908
  // check if this plan is the optimal plan we found for this set of relations
145323
145909
  auto entry = plans.find(new_set);
145324
- if (entry == plans.end() || new_plan->cost < entry->second->cost) {
145910
+ if (entry == plans.end() || new_plan->GetCost() < entry->second->GetCost()) {
145325
145911
  // the plan is the optimal plan, move it into the dynamic programming tree
145326
145912
  auto result = new_plan.get();
145913
+ //! make sure plans are symmetric for cardinality estimation
145914
+ if (entry != plans.end()) {
145915
+ cardinality_estimator.VerifySymmetry(result, entry->second.get());
145916
+ }
145917
+
145918
+ if (full_plan_found && join_nodes_in_full_plan.count(new_plan.get()) > 0) {
145919
+ must_update_full_plan = true;
145920
+ }
145921
+ if (new_set->count == relations.size()) {
145922
+ full_plan_found = true;
145923
+ // If we find a full plan, we need to keep track of which nodes are in the full plan.
145924
+ // It's possible the DP algorithm updates one of these nodes, then goes on to solve
145925
+ // the order approximately. In the approximate algorithm, it's not guaranteed that the
145926
+ // node references are updated. If the original full plan is determined to still have
145927
+ // the lowest cost, it's possible to get use-after-free errors.
145928
+ // If we know a node in the full plan is updated, we can prevent ourselves from exiting the
145929
+ // DP algorithm until the last plan updated is a full plan
145930
+ UpdateJoinNodesInFullPlan(result);
145931
+ if (must_update_full_plan) {
145932
+ must_update_full_plan = false;
145933
+ }
145934
+ }
145935
+
145327
145936
  plans[new_set] = move(new_plan);
145328
145937
  return result;
145329
145938
  }
145330
145939
  return entry->second.get();
145331
145940
  }
145332
145941
 
145333
- bool JoinOrderOptimizer::TryEmitPair(JoinRelationSet *left, JoinRelationSet *right, NeighborInfo *info) {
145942
+ bool JoinOrderOptimizer::TryEmitPair(JoinRelationSet *left, JoinRelationSet *right,
145943
+ const vector<NeighborInfo *> &info) {
145334
145944
  pairs++;
145335
- if (pairs >= 2000) {
145945
+ // If a full plan is created, it's possible a node in the plan gets updated. When this happens, make sure you keep
145946
+ // emitting pairs until you emit another final plan. Another final plan is guaranteed to be produced because of
145947
+ // our symmetry guarantees.
145948
+ if (pairs >= 10000 && !must_update_full_plan) {
145336
145949
  // when the amount of pairs gets too large we exit the dynamic programming and resort to a greedy algorithm
145337
145950
  // FIXME: simple heuristic currently
145338
145951
  // at 10K pairs stop searching exactly and switch to heuristic
@@ -145357,15 +145970,19 @@ bool JoinOrderOptimizer::EmitCSG(JoinRelationSet *node) {
145357
145970
  if (neighbors.empty()) {
145358
145971
  return true;
145359
145972
  }
145360
- // we iterate over the neighbors ordered by their first node
145361
- sort(neighbors.begin(), neighbors.end());
145973
+
145974
+ //! Neighbors should be reversed when iterating over them.
145975
+ std::sort(neighbors.begin(), neighbors.end(), std::greater_equal<idx_t>());
145976
+ for (idx_t i = 0; i < neighbors.size() - 1; i++) {
145977
+ D_ASSERT(neighbors[i] >= neighbors[i + 1]);
145978
+ }
145362
145979
  for (auto neighbor : neighbors) {
145363
145980
  // since the GetNeighbors only returns the smallest element in a list, the entry might not be connected to
145364
145981
  // (only!) this neighbor, hence we have to do a connectedness check before we can emit it
145365
145982
  auto neighbor_relation = set_manager.GetJoinRelation(neighbor);
145366
- auto connection = query_graph.GetConnection(node, neighbor_relation);
145367
- if (connection) {
145368
- if (!TryEmitPair(node, neighbor_relation, connection)) {
145983
+ auto connections = query_graph.GetConnections(node, neighbor_relation);
145984
+ if (!connections.empty()) {
145985
+ if (!TryEmitPair(node, neighbor_relation, connections)) {
145369
145986
  return false;
145370
145987
  }
145371
145988
  }
@@ -145390,9 +146007,9 @@ bool JoinOrderOptimizer::EnumerateCmpRecursive(JoinRelationSet *left, JoinRelati
145390
146007
  // emit the combinations of this node and its neighbors
145391
146008
  auto combined_set = set_manager.Union(right, neighbor);
145392
146009
  if (combined_set->count > right->count && plans.find(combined_set) != plans.end()) {
145393
- auto connection = query_graph.GetConnection(left, combined_set);
145394
- if (connection) {
145395
- if (!TryEmitPair(left, combined_set, connection)) {
146010
+ auto connections = query_graph.GetConnections(left, combined_set);
146011
+ if (!connections.empty()) {
146012
+ if (!TryEmitPair(left, combined_set, connections)) {
145396
146013
  return false;
145397
146014
  }
145398
146015
  }
@@ -145412,12 +146029,11 @@ bool JoinOrderOptimizer::EnumerateCmpRecursive(JoinRelationSet *left, JoinRelati
145412
146029
  }
145413
146030
 
145414
146031
  bool JoinOrderOptimizer::EnumerateCSGRecursive(JoinRelationSet *node, unordered_set<idx_t> &exclusion_set) {
145415
- // find neighbors of S under the exlusion set
146032
+ // find neighbors of S under the exclusion set
145416
146033
  auto neighbors = query_graph.GetNeighbors(node, exclusion_set);
145417
146034
  if (neighbors.empty()) {
145418
146035
  return true;
145419
146036
  }
145420
- // now first emit the connected subgraphs of the neighbors
145421
146037
  vector<JoinRelationSet *> union_sets;
145422
146038
  union_sets.resize(neighbors.size());
145423
146039
  for (idx_t i = 0; i < neighbors.size(); i++) {
@@ -145434,8 +146050,11 @@ bool JoinOrderOptimizer::EnumerateCSGRecursive(JoinRelationSet *node, unordered_
145434
146050
  // recursively enumerate the sets
145435
146051
  unordered_set<idx_t> new_exclusion_set = exclusion_set;
145436
146052
  for (idx_t i = 0; i < neighbors.size(); i++) {
145437
- // updated the set of excluded entries with this neighbor
146053
+ // Reset the exclusion set so that the algorithm considers all combinations
146054
+ // of the exclusion_set with a subset of neighbors.
146055
+ new_exclusion_set = exclusion_set;
145438
146056
  new_exclusion_set.insert(neighbors[i]);
146057
+ // updated the set of excluded entries with this neighbor
145439
146058
  if (!EnumerateCSGRecursive(union_sets[i], new_exclusion_set)) {
145440
146059
  return false;
145441
146060
  }
@@ -145466,6 +146085,99 @@ bool JoinOrderOptimizer::SolveJoinOrderExactly() {
145466
146085
  return true;
145467
146086
  }
145468
146087
 
146088
+ static vector<unordered_set<idx_t>> AddSuperSets(vector<unordered_set<idx_t>> current,
146089
+ const vector<idx_t> &all_neighbors) {
146090
+ vector<unordered_set<idx_t>> ret;
146091
+ for (auto &neighbor : all_neighbors) {
146092
+ for (auto &neighbor_set : current) {
146093
+ auto max_val = std::max_element(neighbor_set.begin(), neighbor_set.end());
146094
+ if (*max_val >= neighbor) {
146095
+ continue;
146096
+ }
146097
+ if (neighbor_set.count(neighbor) == 0) {
146098
+ unordered_set<idx_t> new_set;
146099
+ for (auto &n : neighbor_set) {
146100
+ new_set.insert(n);
146101
+ }
146102
+ new_set.insert(neighbor);
146103
+ ret.push_back(new_set);
146104
+ }
146105
+ }
146106
+ }
146107
+ return ret;
146108
+ }
146109
+
146110
+ // works by first creating all sets with cardinality 1
146111
+ // then iterates over each previously create group of subsets and will only add a neighbor if the neighbor
146112
+ // is greater than all relations in the set.
146113
+ static vector<unordered_set<idx_t>> GetAllNeighborSets(JoinRelationSet *new_set, unordered_set<idx_t> &exclusion_set,
146114
+ vector<idx_t> neighbors) {
146115
+ vector<unordered_set<idx_t>> ret;
146116
+ sort(neighbors.begin(), neighbors.end());
146117
+ vector<unordered_set<idx_t>> added;
146118
+ for (auto &neighbor : neighbors) {
146119
+ added.push_back(unordered_set<idx_t>({neighbor}));
146120
+ ret.push_back(unordered_set<idx_t>({neighbor}));
146121
+ }
146122
+ do {
146123
+ added = AddSuperSets(added, neighbors);
146124
+ for (auto &d : added) {
146125
+ ret.push_back(d);
146126
+ }
146127
+ } while (!added.empty());
146128
+ #if DEBUG
146129
+ // drive by test to make sure we have an accurate amount of
146130
+ // subsets, and that each neighbor is in a correct amount
146131
+ // of those subsets.
146132
+ D_ASSERT(ret.size() == pow(2, neighbors.size()) - 1);
146133
+ for (auto &n : neighbors) {
146134
+ idx_t count = 0;
146135
+ for (auto &set : ret) {
146136
+ if (set.count(n) >= 1) {
146137
+ count += 1;
146138
+ }
146139
+ }
146140
+ D_ASSERT(count == pow(2, neighbors.size() - 1));
146141
+ }
146142
+ #endif
146143
+ return ret;
146144
+ }
146145
+
146146
+ void JoinOrderOptimizer::UpdateDPTree(JoinNode *new_plan) {
146147
+ auto new_set = new_plan->set;
146148
+ // now update every plan that uses this plan
146149
+ unordered_set<idx_t> exclusion_set;
146150
+ for (idx_t i = 0; i < new_set->count; i++) {
146151
+ exclusion_set.insert(new_set->relations[i]);
146152
+ }
146153
+ auto neighbors = query_graph.GetNeighbors(new_set, exclusion_set);
146154
+ auto all_neighbors = GetAllNeighborSets(new_set, exclusion_set, neighbors);
146155
+ for (auto neighbor : all_neighbors) {
146156
+ auto neighbor_relation = set_manager.GetJoinRelation(neighbor);
146157
+ auto combined_set = set_manager.Union(new_set, neighbor_relation);
146158
+
146159
+ auto combined_set_plan = plans.find(combined_set);
146160
+ if (combined_set_plan == plans.end()) {
146161
+ continue;
146162
+ }
146163
+
146164
+ double combined_set_plan_cost = combined_set_plan->second->GetCost();
146165
+ auto connections = query_graph.GetConnections(new_set, neighbor_relation);
146166
+ // recurse and update up the tree if the combined set produces a plan with a lower cost
146167
+ // only recurse on neighbor relations that have plans.
146168
+ auto &right_plan = plans[neighbor_relation];
146169
+ if (!right_plan) {
146170
+ continue;
146171
+ }
146172
+ auto updated_plan = EmitPair(new_set, neighbor_relation, connections);
146173
+ // <= because the child node has already been replaced. You need to
146174
+ // replace the parent node as well in this case
146175
+ if (updated_plan->GetCost() < combined_set_plan_cost) {
146176
+ UpdateDPTree(updated_plan);
146177
+ }
146178
+ }
146179
+ }
146180
+
145469
146181
  void JoinOrderOptimizer::SolveJoinOrderApproximately() {
145470
146182
  // at this point, we exited the dynamic programming but did not compute the final join order because it took too
145471
146183
  // long instead, we use a greedy heuristic to obtain a join ordering now we use Greedy Operator Ordering to
@@ -145485,11 +146197,17 @@ void JoinOrderOptimizer::SolveJoinOrderApproximately() {
145485
146197
  for (idx_t j = i + 1; j < join_relations.size(); j++) {
145486
146198
  auto right = join_relations[j];
145487
146199
  // check if we can connect these two relations
145488
- auto connection = query_graph.GetConnection(left, right);
145489
- if (connection) {
145490
- // we can! check the cost of this connection
146200
+ auto connection = query_graph.GetConnections(left, right);
146201
+ if (!connection.empty()) {
146202
+ // we can check the cost of this connection
145491
146203
  auto node = EmitPair(left, right, connection);
145492
- if (!best_connection || node->cost < best_connection->cost) {
146204
+
146205
+ // update the DP tree in case a plan created by the DP algorithm uses the node
146206
+ // that was potentially just updated by EmitPair. You will get a use-after-free
146207
+ // error if future plans rely on the old node that was just replaced.
146208
+ UpdateDPTree(node);
146209
+
146210
+ if (!best_connection || node->GetCost() < best_connection->GetCost()) {
145493
146211
  // best pair found so far
145494
146212
  best_connection = node;
145495
146213
  best_left = i;
@@ -145508,7 +146226,7 @@ void JoinOrderOptimizer::SolveJoinOrderApproximately() {
145508
146226
  auto current_plan = plans[join_relations[i]].get();
145509
146227
  // check if the cardinality is smaller than the smallest two found so far
145510
146228
  for (idx_t j = 0; j < 2; j++) {
145511
- if (!smallest_plans[j] || smallest_plans[j]->cardinality > current_plan->cardinality) {
146229
+ if (!smallest_plans[j] || smallest_plans[j]->GetCardinality() > current_plan->GetCardinality()) {
145512
146230
  smallest_plans[j] = current_plan;
145513
146231
  smallest_index[j] = i;
145514
146232
  break;
@@ -145525,12 +146243,14 @@ void JoinOrderOptimizer::SolveJoinOrderApproximately() {
145525
146243
  // create a cross product edge (i.e. edge with empty filter) between these two sets in the query graph
145526
146244
  query_graph.CreateEdge(left, right, nullptr);
145527
146245
  // now emit the pair and continue with the algorithm
145528
- auto connection = query_graph.GetConnection(left, right);
145529
- D_ASSERT(connection);
146246
+ auto connections = query_graph.GetConnections(left, right);
146247
+ D_ASSERT(!connections.empty());
145530
146248
 
145531
- best_connection = EmitPair(left, right, connection);
146249
+ best_connection = EmitPair(left, right, connections);
145532
146250
  best_left = smallest_index[0];
145533
146251
  best_right = smallest_index[1];
146252
+
146253
+ UpdateDPTree(best_connection);
145534
146254
  // the code below assumes best_right > best_left
145535
146255
  if (best_left > best_right) {
145536
146256
  std::swap(best_left, best_right);
@@ -145632,6 +146352,7 @@ JoinOrderOptimizer::GenerateJoins(vector<unique_ptr<LogicalOperator>> &extracted
145632
146352
  }
145633
146353
  left_node = left.first;
145634
146354
  right_node = right.first;
146355
+ right_node = right.first;
145635
146356
  result_relation = set_manager.Union(left_node, right_node);
145636
146357
  } else {
145637
146358
  // base node, get the entry from the list of extracted relations
@@ -145640,6 +146361,10 @@ JoinOrderOptimizer::GenerateJoins(vector<unique_ptr<LogicalOperator>> &extracted
145640
146361
  result_relation = node->set;
145641
146362
  result_operator = move(extracted_relations[node->set->relations[0]]);
145642
146363
  }
146364
+ auto max_idx_t = NumericLimits<idx_t>::Maximum() - 10000;
146365
+ result_operator->estimated_cardinality = MinValue<idx_t>(node->GetCardinality(), max_idx_t);
146366
+ result_operator->has_estimated_cardinality = true;
146367
+ result_operator->estimated_props = node->estimated_props->Copy();
145643
146368
  // check if we should do a pushdown on this node
145644
146369
  // basically, any remaining filter that is a subset of the current relation will no longer be used in joins
145645
146370
  // hence we should push it here
@@ -145813,6 +146538,7 @@ unique_ptr<LogicalOperator> JoinOrderOptimizer::Optimize(unique_ptr<LogicalOpera
145813
146538
  // first extract the relation set for the entire filter
145814
146539
  unordered_set<idx_t> bindings;
145815
146540
  ExtractBindings(*filter, bindings);
146541
+ GetColumnBindings(*filter, filter_info->left_binding, filter_info->right_binding);
145816
146542
  filter_info->set = set_manager.GetJoinRelation(bindings);
145817
146543
  filter_info->filter_index = i;
145818
146544
  // now check if it can be used as a join predicate
@@ -145846,10 +146572,17 @@ unique_ptr<LogicalOperator> JoinOrderOptimizer::Optimize(unique_ptr<LogicalOpera
145846
146572
  // First we initialize each of the single-node plans with themselves and with their cardinalities these are the leaf
145847
146573
  // nodes of the join tree NOTE: we can just use pointers to JoinRelationSet* here because the GetJoinRelation
145848
146574
  // function ensures that a unique combination of relations will have a unique JoinRelationSet object.
146575
+ vector<NodeOp> nodes_ops;
145849
146576
  for (idx_t i = 0; i < relations.size(); i++) {
145850
146577
  auto &rel = *relations[i];
145851
146578
  auto node = set_manager.GetJoinRelation(i);
145852
- plans[node] = make_unique<JoinNode>(node, rel.op->EstimateCardinality(context));
146579
+ nodes_ops.emplace_back(NodeOp(make_unique<JoinNode>(node, 0), rel.op));
146580
+ }
146581
+
146582
+ cardinality_estimator.InitCardinalityEstimatorProps(&nodes_ops, &filter_infos);
146583
+
146584
+ for (auto &node_op : nodes_ops) {
146585
+ plans[node_op.node->set] = move(node_op.node);
145853
146586
  }
145854
146587
  // now we perform the actual dynamic programming to compute the final result
145855
146588
  SolveJoinOrder();
@@ -149001,7 +149734,7 @@ unique_ptr<Expression> MoveConstantsRule::Apply(LogicalOperator &op, vector<Expr
149001
149734
 
149002
149735
 
149003
149736
  // LICENSE_CHANGE_BEGIN
149004
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
149737
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
149005
149738
  // See the end of this file for a list
149006
149739
 
149007
149740
  // Copyright 2006 The RE2 Authors. All Rights Reserved.
@@ -149100,7 +149833,7 @@ unique_ptr<Expression> MoveConstantsRule::Apply(LogicalOperator &op, vector<Expr
149100
149833
 
149101
149834
 
149102
149835
  // LICENSE_CHANGE_BEGIN
149103
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
149836
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
149104
149837
  // See the end of this file for a list
149105
149838
 
149106
149839
  // Copyright 2009 The RE2 Authors. All Rights Reserved.
@@ -149144,7 +149877,7 @@ unique_ptr<Expression> MoveConstantsRule::Apply(LogicalOperator &op, vector<Expr
149144
149877
 
149145
149878
 
149146
149879
  // LICENSE_CHANGE_BEGIN
149147
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
149880
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
149148
149881
  // See the end of this file for a list
149149
149882
 
149150
149883
  // Copyright 2009 The RE2 Authors. All Rights Reserved.
@@ -149269,7 +150002,7 @@ class LogMessageFatal : public LogMessage {
149269
150002
 
149270
150003
 
149271
150004
  // LICENSE_CHANGE_BEGIN
149272
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
150005
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
149273
150006
  // See the end of this file for a list
149274
150007
 
149275
150008
  /*
@@ -180292,7 +181025,9 @@ BoundStatement Binder::Bind(VacuumStatement &stmt) {
180292
181025
  for (auto &col_name : columns) {
180293
181026
  ColumnRefExpression colref(col_name, ref->table->name);
180294
181027
  auto result = bind_context.BindColumn(colref, 0);
180295
- D_ASSERT(!result.HasError());
181028
+ if (result.HasError()) {
181029
+ throw BinderException(result.error);
181030
+ }
180296
181031
  select_list.push_back(move(result.expression));
180297
181032
  }
180298
181033
  auto table_scan = CreatePlan(*ref);
@@ -185393,11 +186128,12 @@ namespace duckdb {
185393
186128
 
185394
186129
  const uint64_t PLAN_SERIALIZATION_VERSION = 1;
185395
186130
 
185396
- LogicalOperator::LogicalOperator(LogicalOperatorType type) : type(type) {
186131
+ LogicalOperator::LogicalOperator(LogicalOperatorType type)
186132
+ : type(type), estimated_cardinality(0), has_estimated_cardinality(false) {
185397
186133
  }
185398
186134
 
185399
186135
  LogicalOperator::LogicalOperator(LogicalOperatorType type, vector<unique_ptr<Expression>> expressions)
185400
- : type(type), expressions(move(expressions)) {
186136
+ : type(type), expressions(move(expressions)), estimated_cardinality(0), has_estimated_cardinality(false) {
185401
186137
  }
185402
186138
 
185403
186139
  LogicalOperator::~LogicalOperator() {
@@ -185539,10 +186275,14 @@ void LogicalOperator::AddChild(unique_ptr<LogicalOperator> child) {
185539
186275
 
185540
186276
  idx_t LogicalOperator::EstimateCardinality(ClientContext &context) {
185541
186277
  // simple estimator, just take the max of the children
186278
+ if (has_estimated_cardinality) {
186279
+ return estimated_cardinality;
186280
+ }
185542
186281
  idx_t max_cardinality = 0;
185543
186282
  for (auto &child : children) {
185544
186283
  max_cardinality = MaxValue(child->EstimateCardinality(context), max_cardinality);
185545
186284
  }
186285
+ has_estimated_cardinality = true;
185546
186286
  return max_cardinality;
185547
186287
  }
185548
186288
 
@@ -198556,6 +199296,14 @@ void BaseStatistics::Merge(const BaseStatistics &other) {
198556
199296
  }
198557
199297
  }
198558
199298
 
199299
+ idx_t BaseStatistics::GetDistinctCount() {
199300
+ if (distinct_stats) {
199301
+ auto &d_stats = (DistinctStatistics &)*distinct_stats;
199302
+ return d_stats.GetCount();
199303
+ }
199304
+ return 0;
199305
+ }
199306
+
198559
199307
  unique_ptr<BaseStatistics> BaseStatistics::CreateEmpty(LogicalType type, StatisticsType stats_type) {
198560
199308
  unique_ptr<BaseStatistics> result;
198561
199309
  switch (type.InternalType()) {
@@ -207413,7 +208161,7 @@ unique_ptr<StatementVerifier> UnoptimizedStatementVerifier::Create(const SQLStat
207413
208161
 
207414
208162
 
207415
208163
  // LICENSE_CHANGE_BEGIN
207416
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
208164
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3
207417
208165
  // See the end of this file for a list
207418
208166
 
207419
208167
  // Formatting library for C++
@@ -207426,7 +208174,7 @@ unique_ptr<StatementVerifier> UnoptimizedStatementVerifier::Create(const SQLStat
207426
208174
 
207427
208175
 
207428
208176
  // LICENSE_CHANGE_BEGIN
207429
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
208177
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3
207430
208178
  // See the end of this file for a list
207431
208179
 
207432
208180
  // Formatting library for C++ - implementation
@@ -208823,7 +209571,7 @@ FMT_END_NAMESPACE
208823
209571
 
208824
209572
 
208825
209573
  // LICENSE_CHANGE_BEGIN
208826
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #4
209574
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5
208827
209575
  // See the end of this file for a list
208828
209576
 
208829
209577
  /**************************************************************************
@@ -216375,7 +217123,7 @@ mz_bool mz_zip_end(mz_zip_archive *pZip)
216375
217123
 
216376
217124
 
216377
217125
  // LICENSE_CHANGE_BEGIN
216378
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
217126
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
216379
217127
  // See the end of this file for a list
216380
217128
 
216381
217129
  // Copyright 2008 The RE2 Authors. All Rights Reserved.
@@ -216407,7 +217155,7 @@ mz_bool mz_zip_end(mz_zip_archive *pZip)
216407
217155
 
216408
217156
 
216409
217157
  // LICENSE_CHANGE_BEGIN
216410
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
217158
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
216411
217159
  // See the end of this file for a list
216412
217160
 
216413
217161
  // Copyright 2018 The RE2 Authors. All Rights Reserved.
@@ -216472,7 +217220,7 @@ class PODArray {
216472
217220
 
216473
217221
 
216474
217222
  // LICENSE_CHANGE_BEGIN
216475
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
217223
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
216476
217224
  // See the end of this file for a list
216477
217225
 
216478
217226
  // Copyright 2007 The RE2 Authors. All Rights Reserved.
@@ -216499,7 +217247,7 @@ class PODArray {
216499
217247
 
216500
217248
 
216501
217249
  // LICENSE_CHANGE_BEGIN
216502
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
217250
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
216503
217251
  // See the end of this file for a list
216504
217252
 
216505
217253
  // Copyright 2006 The RE2 Authors. All Rights Reserved.
@@ -216901,7 +217649,7 @@ template<typename Value> bool SparseArray<Value>::less(const IndexValue& a,
216901
217649
 
216902
217650
 
216903
217651
  // LICENSE_CHANGE_BEGIN
216904
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
217652
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
216905
217653
  // See the end of this file for a list
216906
217654
 
216907
217655
  // Copyright 2006 The RE2 Authors. All Rights Reserved.
@@ -217943,7 +218691,7 @@ bool Prog::SearchBitState(const StringPiece& text,
217943
218691
 
217944
218692
 
217945
218693
  // LICENSE_CHANGE_BEGIN
217946
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
218694
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
217947
218695
  // See the end of this file for a list
217948
218696
 
217949
218697
  // Copyright 2007 The RE2 Authors. All Rights Reserved.
@@ -217970,7 +218718,7 @@ bool Prog::SearchBitState(const StringPiece& text,
217970
218718
 
217971
218719
 
217972
218720
  // LICENSE_CHANGE_BEGIN
217973
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
218721
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
217974
218722
  // See the end of this file for a list
217975
218723
 
217976
218724
  // Copyright 2006 The RE2 Authors. All Rights Reserved.
@@ -219486,7 +220234,7 @@ Prog* Prog::CompileSet(Regexp* re, RE2::Anchor anchor, int64_t max_mem) {
219486
220234
 
219487
220235
 
219488
220236
  // LICENSE_CHANGE_BEGIN
219489
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
220237
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
219490
220238
  // See the end of this file for a list
219491
220239
 
219492
220240
  // Copyright 2008 The RE2 Authors. All Rights Reserved.
@@ -219531,7 +220279,7 @@ Prog* Prog::CompileSet(Regexp* re, RE2::Anchor anchor, int64_t max_mem) {
219531
220279
 
219532
220280
 
219533
220281
  // LICENSE_CHANGE_BEGIN
219534
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
220282
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
219535
220283
  // See the end of this file for a list
219536
220284
 
219537
220285
  // Copyright 2016 The RE2 Authors. All Rights Reserved.
@@ -219582,7 +220330,7 @@ class HashMix {
219582
220330
 
219583
220331
 
219584
220332
  // LICENSE_CHANGE_BEGIN
219585
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
220333
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
219586
220334
  // See the end of this file for a list
219587
220335
 
219588
220336
  // Copyright 2007 The RE2 Authors. All Rights Reserved.
@@ -219726,7 +220474,7 @@ class WriterMutexLock {
219726
220474
 
219727
220475
 
219728
220476
  // LICENSE_CHANGE_BEGIN
219729
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
220477
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
219730
220478
  // See the end of this file for a list
219731
220479
 
219732
220480
  // Copyright 2016 The RE2 Authors. All Rights Reserved.
@@ -221802,7 +222550,7 @@ bool Prog::PossibleMatchRange(std::string* min, std::string* max, int maxlen) {
221802
222550
 
221803
222551
 
221804
222552
  // LICENSE_CHANGE_BEGIN
221805
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
222553
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
221806
222554
  // See the end of this file for a list
221807
222555
 
221808
222556
  // Copyright 2009 The RE2 Authors. All Rights Reserved.
@@ -221812,7 +222560,7 @@ bool Prog::PossibleMatchRange(std::string* min, std::string* max, int maxlen) {
221812
222560
 
221813
222561
 
221814
222562
  // LICENSE_CHANGE_BEGIN
221815
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
222563
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
221816
222564
  // See the end of this file for a list
221817
222565
 
221818
222566
  // Copyright 2009 The RE2 Authors. All Rights Reserved.
@@ -221938,7 +222686,7 @@ class FilteredRE2 {
221938
222686
 
221939
222687
 
221940
222688
  // LICENSE_CHANGE_BEGIN
221941
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
222689
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
221942
222690
  // See the end of this file for a list
221943
222691
 
221944
222692
  // Copyright 2009 The RE2 Authors. All Rights Reserved.
@@ -222056,7 +222804,7 @@ class Prefilter {
222056
222804
 
222057
222805
 
222058
222806
  // LICENSE_CHANGE_BEGIN
222059
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
222807
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
222060
222808
  // See the end of this file for a list
222061
222809
 
222062
222810
  // Copyright 2009 The RE2 Authors. All Rights Reserved.
@@ -222316,7 +223064,7 @@ void FilteredRE2::PrintPrefilter(int regexpid) {
222316
223064
 
222317
223065
 
222318
223066
  // LICENSE_CHANGE_BEGIN
222319
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
223067
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
222320
223068
  // See the end of this file for a list
222321
223069
 
222322
223070
  // Copyright 2008 The RE2 Authors. All Rights Reserved.
@@ -222512,7 +223260,7 @@ static bool CanBeEmptyString(Regexp* re) {
222512
223260
 
222513
223261
 
222514
223262
  // LICENSE_CHANGE_BEGIN
222515
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
223263
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
222516
223264
  // See the end of this file for a list
222517
223265
 
222518
223266
  // Copyright 2006-2007 The RE2 Authors. All Rights Reserved.
@@ -223235,7 +223983,7 @@ void Prog::Fanout(SparseArray<int>* fanout) {
223235
223983
 
223236
223984
 
223237
223985
  // LICENSE_CHANGE_BEGIN
223238
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
223986
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
223239
223987
  // See the end of this file for a list
223240
223988
 
223241
223989
  // Copyright 2008 The RE2 Authors. All Rights Reserved.
@@ -223819,7 +224567,7 @@ fail:
223819
224567
 
223820
224568
 
223821
224569
  // LICENSE_CHANGE_BEGIN
223822
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
224570
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
223823
224571
  // See the end of this file for a list
223824
224572
 
223825
224573
  // Copyright 2006 The RE2 Authors. All Rights Reserved.
@@ -223859,7 +224607,7 @@ fail:
223859
224607
 
223860
224608
 
223861
224609
  // LICENSE_CHANGE_BEGIN
223862
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
224610
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
223863
224611
  // See the end of this file for a list
223864
224612
 
223865
224613
  // Copyright 2008 The RE2 Authors. All Rights Reserved.
@@ -223947,7 +224695,7 @@ extern Rune ApplyFold(const CaseFold *f, Rune r);
223947
224695
 
223948
224696
 
223949
224697
  // LICENSE_CHANGE_BEGIN
223950
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
224698
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
223951
224699
  // See the end of this file for a list
223952
224700
 
223953
224701
  // Copyright 2008 The RE2 Authors. All Rights Reserved.
@@ -226455,7 +227203,7 @@ Regexp* Regexp::Parse(const StringPiece& s, ParseFlags global_flags,
226455
227203
 
226456
227204
 
226457
227205
  // LICENSE_CHANGE_BEGIN
226458
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
227206
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
226459
227207
  // See the end of this file for a list
226460
227208
 
226461
227209
  // GENERATED BY make_perl_groups.pl; DO NOT EDIT.
@@ -226583,7 +227331,7 @@ const int num_posix_groups = 28;
226583
227331
 
226584
227332
 
226585
227333
  // LICENSE_CHANGE_BEGIN
226586
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
227334
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
226587
227335
  // See the end of this file for a list
226588
227336
 
226589
227337
  // Copyright 2009 The RE2 Authors. All Rights Reserved.
@@ -227284,7 +228032,7 @@ Prefilter* Prefilter::FromRE2(const RE2* re2) {
227284
228032
 
227285
228033
 
227286
228034
  // LICENSE_CHANGE_BEGIN
227287
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
228035
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
227288
228036
  // See the end of this file for a list
227289
228037
 
227290
228038
  // Copyright 2009 The RE2 Authors. All Rights Reserved.
@@ -227695,7 +228443,7 @@ std::string PrefilterTree::DebugNodeString(Prefilter* node) const {
227695
228443
 
227696
228444
 
227697
228445
  // LICENSE_CHANGE_BEGIN
227698
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
228446
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
227699
228447
  // See the end of this file for a list
227700
228448
 
227701
228449
  // Copyright 2007 The RE2 Authors. All Rights Reserved.
@@ -227719,7 +228467,7 @@ std::string PrefilterTree::DebugNodeString(Prefilter* node) const {
227719
228467
 
227720
228468
 
227721
228469
  // LICENSE_CHANGE_BEGIN
227722
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
228470
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
227723
228471
  // See the end of this file for a list
227724
228472
 
227725
228473
  // Copyright 2016 The RE2 Authors. All Rights Reserved.
@@ -228745,7 +229493,7 @@ void Prog::ComputeHints(std::vector<Inst>* flat, int begin, int end) {
228745
229493
 
228746
229494
 
228747
229495
  // LICENSE_CHANGE_BEGIN
228748
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
229496
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
228749
229497
  // See the end of this file for a list
228750
229498
 
228751
229499
  // Copyright 2003-2009 The RE2 Authors. All Rights Reserved.
@@ -229989,7 +230737,7 @@ DEFINE_INTEGER_PARSER(ulonglong)
229989
230737
 
229990
230738
 
229991
230739
  // LICENSE_CHANGE_BEGIN
229992
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
230740
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
229993
230741
  // See the end of this file for a list
229994
230742
 
229995
230743
  // Copyright 2006 The RE2 Authors. All Rights Reserved.
@@ -230969,7 +231717,7 @@ CharClass* CharClassBuilder::GetCharClass() {
230969
231717
 
230970
231718
 
230971
231719
  // LICENSE_CHANGE_BEGIN
230972
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
231720
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
230973
231721
  // See the end of this file for a list
230974
231722
 
230975
231723
  // Copyright 2010 The RE2 Authors. All Rights Reserved.
@@ -230979,7 +231727,7 @@ CharClass* CharClassBuilder::GetCharClass() {
230979
231727
 
230980
231728
 
230981
231729
  // LICENSE_CHANGE_BEGIN
230982
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
231730
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
230983
231731
  // See the end of this file for a list
230984
231732
 
230985
231733
  // Copyright 2010 The RE2 Authors. All Rights Reserved.
@@ -231220,7 +231968,7 @@ bool RE2::Set::Match(const StringPiece& text, std::vector<int>* v,
231220
231968
 
231221
231969
 
231222
231970
  // LICENSE_CHANGE_BEGIN
231223
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
231971
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
231224
231972
  // See the end of this file for a list
231225
231973
 
231226
231974
  // Copyright 2006 The RE2 Authors. All Rights Reserved.
@@ -231885,7 +232633,7 @@ Regexp* SimplifyWalker::SimplifyCharClass(Regexp* re) {
231885
232633
 
231886
232634
 
231887
232635
  // LICENSE_CHANGE_BEGIN
231888
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
232636
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
231889
232637
  // See the end of this file for a list
231890
232638
 
231891
232639
  // Copyright 2004 The RE2 Authors. All Rights Reserved.
@@ -231959,7 +232707,7 @@ std::ostream& operator<<(std::ostream& o, const StringPiece& p) {
231959
232707
 
231960
232708
 
231961
232709
  // LICENSE_CHANGE_BEGIN
231962
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
232710
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
231963
232711
  // See the end of this file for a list
231964
232712
 
231965
232713
  // Copyright 2006 The RE2 Authors. All Rights Reserved.
@@ -232317,7 +233065,7 @@ static void AppendCCRange(std::string* t, Rune lo, Rune hi) {
232317
233065
 
232318
233066
 
232319
233067
  // LICENSE_CHANGE_BEGIN
232320
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
233068
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
232321
233069
  // See the end of this file for a list
232322
233070
 
232323
233071
 
@@ -232893,7 +233641,7 @@ const int num_unicode_tolower = 194;
232893
233641
 
232894
233642
 
232895
233643
  // LICENSE_CHANGE_BEGIN
232896
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
233644
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
232897
233645
  // See the end of this file for a list
232898
233646
 
232899
233647
 
@@ -238961,7 +239709,7 @@ const int num_unicode_groups = 184;
238961
239709
 
238962
239710
 
238963
239711
  // LICENSE_CHANGE_BEGIN
238964
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
239712
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
238965
239713
  // See the end of this file for a list
238966
239714
 
238967
239715
  /*
@@ -239230,7 +239978,7 @@ utfrune(const char *s, Rune c)
239230
239978
 
239231
239979
 
239232
239980
  // LICENSE_CHANGE_BEGIN
239233
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
239981
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2
239234
239982
  // See the end of this file for a list
239235
239983
 
239236
239984
  // Copyright 1999-2005 The RE2 Authors. All Rights Reserved.
@@ -239403,7 +240151,7 @@ void StringAppendF(std::string* dst, const char* format, ...) {
239403
240151
 
239404
240152
 
239405
240153
  // LICENSE_CHANGE_BEGIN
239406
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #7
240154
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
239407
240155
  // See the end of this file for a list
239408
240156
 
239409
240157
  /* hyperloglog.c - Redis HyperLogLog probabilistic cardinality approximation.
@@ -239444,7 +240192,7 @@ void StringAppendF(std::string* dst, const char* format, ...) {
239444
240192
 
239445
240193
 
239446
240194
  // LICENSE_CHANGE_BEGIN
239447
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #7
240195
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
239448
240196
  // See the end of this file for a list
239449
240197
 
239450
240198
  /* SDSLib 2.0 -- A C dynamic strings library
@@ -240991,7 +241739,7 @@ void AddToSingleLogInternal(UnifiedVectorFormat &vdata, idx_t count, uint64_t in
240991
241739
 
240992
241740
 
240993
241741
  // LICENSE_CHANGE_BEGIN
240994
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #7
241742
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1
240995
241743
  // See the end of this file for a list
240996
241744
 
240997
241745
  /* SDSLib 2.0 -- A C dynamic strings library
@@ -243407,7 +244155,7 @@ void __fastpack64(const uint64_t *__restrict in, uint32_t *__restrict out) {
243407
244155
 
243408
244156
 
243409
244157
  // LICENSE_CHANGE_BEGIN
243410
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3
244158
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #4
243411
244159
  // See the end of this file for a list
243412
244160
 
243413
244161
  /* -*- mode: c; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil -*- */
@@ -243467,7 +244215,7 @@ namespace duckdb {
243467
244215
 
243468
244216
 
243469
244217
  // LICENSE_CHANGE_BEGIN
243470
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3
244218
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #4
243471
244219
  // See the end of this file for a list
243472
244220
 
243473
244221
  static const utf8proc_uint16_t utf8proc_sequences[] = {
@@ -259121,7 +259869,7 @@ UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC_Casefold(const utf8proc_uint8
259121
259869
 
259122
259870
 
259123
259871
  // LICENSE_CHANGE_BEGIN
259124
- // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3
259872
+ // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #4
259125
259873
  // See the end of this file for a list
259126
259874
 
259127
259875
 
@@ -321349,6 +322097,29 @@ bool MbedTlsWrapper::IsValidSha256Signature(const std::string &pubkey, const std
321349
322097
 
321350
322098
  ### THIRD PARTY LICENSE #1 ###
321351
322099
 
322100
+ Copyright (c) 2012 Art.sy, Inc.
322101
+
322102
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
322103
+ this software and associated documentation files (the "Software"), to deal in
322104
+ the Software without restriction, including without limitation the rights to
322105
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
322106
+ of the Software, and to permit persons to whom the Software is furnished to do
322107
+ so, subject to the following conditions:
322108
+
322109
+ The above copyright notice and this permission notice shall be included in all
322110
+ copies or substantial portions of the Software.
322111
+
322112
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
322113
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
322114
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
322115
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
322116
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
322117
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
322118
+ SOFTWARE.
322119
+
322120
+
322121
+ ### THIRD PARTY LICENSE #2 ###
322122
+
321352
322123
  // Copyright (c) 2009 The RE2 Authors. All rights reserved.
321353
322124
  //
321354
322125
  // Redistribution and use in source and binary forms, with or without
@@ -321379,7 +322150,7 @@ bool MbedTlsWrapper::IsValidSha256Signature(const std::string &pubkey, const std
321379
322150
 
321380
322151
 
321381
322152
 
321382
- ### THIRD PARTY LICENSE #2 ###
322153
+ ### THIRD PARTY LICENSE #3 ###
321383
322154
 
321384
322155
  Copyright (c) 2012 - present, Victor Zverovich
321385
322156
 
@@ -321411,7 +322182,7 @@ without including the above copyright and permission notices.
321411
322182
 
321412
322183
 
321413
322184
 
321414
- ### THIRD PARTY LICENSE #3 ###
322185
+ ### THIRD PARTY LICENSE #4 ###
321415
322186
 
321416
322187
  ## utf8proc license ##
321417
322188
 
@@ -321509,7 +322280,7 @@ trademarks mentioned herein are the property of their respective owners.
321509
322280
 
321510
322281
 
321511
322282
 
321512
- ### THIRD PARTY LICENSE #4 ###
322283
+ ### THIRD PARTY LICENSE #5 ###
321513
322284
 
321514
322285
  Copyright 2013-2014 RAD Game Tools and Valve Software
321515
322286
  Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
@@ -321536,7 +322307,7 @@ THE SOFTWARE.
321536
322307
 
321537
322308
 
321538
322309
 
321539
- ### THIRD PARTY LICENSE #5 ###
322310
+ ### THIRD PARTY LICENSE #6 ###
321540
322311
 
321541
322312
  Permission is hereby granted, free of charge, to any
321542
322313
  person obtaining a copy of this software and associated
@@ -321564,7 +322335,7 @@ DEALINGS IN THE SOFTWARE.
321564
322335
 
321565
322336
 
321566
322337
 
321567
- ### THIRD PARTY LICENSE #6 ###
322338
+ ### THIRD PARTY LICENSE #7 ###
321568
322339
 
321569
322340
  Copyright (c) 2014-2017 Melissa O'Neill and PCG Project contributors
321570
322341
 
@@ -321587,29 +322358,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
321587
322358
  SOFTWARE.
321588
322359
 
321589
322360
 
321590
- ### THIRD PARTY LICENSE #7 ###
321591
-
321592
- Copyright (c) 2012 Art.sy, Inc.
321593
-
321594
- Permission is hereby granted, free of charge, to any person obtaining a copy of
321595
- this software and associated documentation files (the "Software"), to deal in
321596
- the Software without restriction, including without limitation the rights to
321597
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
321598
- of the Software, and to permit persons to whom the Software is furnished to do
321599
- so, subject to the following conditions:
321600
-
321601
- The above copyright notice and this permission notice shall be included in all
321602
- copies or substantial portions of the Software.
321603
-
321604
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
321605
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
321606
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
321607
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
321608
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
321609
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
321610
- SOFTWARE.
321611
-
321612
-
321613
322361
  ### THIRD PARTY LICENSE #8 ###
321614
322362
 
321615
322363
  Apache License