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/package.json +1 -1
- package/src/duckdb.cpp +1377 -629
- package/src/duckdb.hpp +1290 -851
- package/src/parquet-amalgamation.cpp +30448 -30448
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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
|
-
|
|
85083
|
+
plan = CreatePlan((LogicalGet &)op);
|
|
85084
|
+
break;
|
|
85260
85085
|
case LogicalOperatorType::LOGICAL_PROJECTION:
|
|
85261
|
-
|
|
85086
|
+
plan = CreatePlan((LogicalProjection &)op);
|
|
85087
|
+
break;
|
|
85262
85088
|
case LogicalOperatorType::LOGICAL_EMPTY_RESULT:
|
|
85263
|
-
|
|
85089
|
+
plan = CreatePlan((LogicalEmptyResult &)op);
|
|
85090
|
+
break;
|
|
85264
85091
|
case LogicalOperatorType::LOGICAL_FILTER:
|
|
85265
|
-
|
|
85092
|
+
plan = CreatePlan((LogicalFilter &)op);
|
|
85093
|
+
break;
|
|
85266
85094
|
case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY:
|
|
85267
|
-
|
|
85095
|
+
plan = CreatePlan((LogicalAggregate &)op);
|
|
85096
|
+
break;
|
|
85268
85097
|
case LogicalOperatorType::LOGICAL_WINDOW:
|
|
85269
|
-
|
|
85098
|
+
plan = CreatePlan((LogicalWindow &)op);
|
|
85099
|
+
break;
|
|
85270
85100
|
case LogicalOperatorType::LOGICAL_UNNEST:
|
|
85271
|
-
|
|
85101
|
+
plan = CreatePlan((LogicalUnnest &)op);
|
|
85102
|
+
break;
|
|
85272
85103
|
case LogicalOperatorType::LOGICAL_LIMIT:
|
|
85273
|
-
|
|
85104
|
+
plan = CreatePlan((LogicalLimit &)op);
|
|
85105
|
+
break;
|
|
85274
85106
|
case LogicalOperatorType::LOGICAL_LIMIT_PERCENT:
|
|
85275
|
-
|
|
85107
|
+
plan = CreatePlan((LogicalLimitPercent &)op);
|
|
85108
|
+
break;
|
|
85276
85109
|
case LogicalOperatorType::LOGICAL_SAMPLE:
|
|
85277
|
-
|
|
85110
|
+
plan = CreatePlan((LogicalSample &)op);
|
|
85111
|
+
break;
|
|
85278
85112
|
case LogicalOperatorType::LOGICAL_ORDER_BY:
|
|
85279
|
-
|
|
85113
|
+
plan = CreatePlan((LogicalOrder &)op);
|
|
85114
|
+
break;
|
|
85280
85115
|
case LogicalOperatorType::LOGICAL_TOP_N:
|
|
85281
|
-
|
|
85116
|
+
plan = CreatePlan((LogicalTopN &)op);
|
|
85117
|
+
break;
|
|
85282
85118
|
case LogicalOperatorType::LOGICAL_COPY_TO_FILE:
|
|
85283
|
-
|
|
85119
|
+
plan = CreatePlan((LogicalCopyToFile &)op);
|
|
85120
|
+
break;
|
|
85284
85121
|
case LogicalOperatorType::LOGICAL_DUMMY_SCAN:
|
|
85285
|
-
|
|
85122
|
+
plan = CreatePlan((LogicalDummyScan &)op);
|
|
85123
|
+
break;
|
|
85286
85124
|
case LogicalOperatorType::LOGICAL_ANY_JOIN:
|
|
85287
|
-
|
|
85125
|
+
plan = CreatePlan((LogicalAnyJoin &)op);
|
|
85126
|
+
break;
|
|
85288
85127
|
case LogicalOperatorType::LOGICAL_DELIM_JOIN:
|
|
85289
|
-
|
|
85128
|
+
plan = CreatePlan((LogicalDelimJoin &)op);
|
|
85129
|
+
break;
|
|
85290
85130
|
case LogicalOperatorType::LOGICAL_COMPARISON_JOIN:
|
|
85291
|
-
|
|
85131
|
+
plan = CreatePlan((LogicalComparisonJoin &)op);
|
|
85132
|
+
break;
|
|
85292
85133
|
case LogicalOperatorType::LOGICAL_CROSS_PRODUCT:
|
|
85293
|
-
|
|
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
|
-
|
|
85139
|
+
plan = CreatePlan((LogicalSetOperation &)op);
|
|
85140
|
+
break;
|
|
85298
85141
|
case LogicalOperatorType::LOGICAL_INSERT:
|
|
85299
|
-
|
|
85142
|
+
plan = CreatePlan((LogicalInsert &)op);
|
|
85143
|
+
break;
|
|
85300
85144
|
case LogicalOperatorType::LOGICAL_DELETE:
|
|
85301
|
-
|
|
85145
|
+
plan = CreatePlan((LogicalDelete &)op);
|
|
85146
|
+
break;
|
|
85302
85147
|
case LogicalOperatorType::LOGICAL_CHUNK_GET:
|
|
85303
|
-
|
|
85148
|
+
plan = CreatePlan((LogicalColumnDataGet &)op);
|
|
85149
|
+
break;
|
|
85304
85150
|
case LogicalOperatorType::LOGICAL_DELIM_GET:
|
|
85305
|
-
|
|
85151
|
+
plan = CreatePlan((LogicalDelimGet &)op);
|
|
85152
|
+
break;
|
|
85306
85153
|
case LogicalOperatorType::LOGICAL_EXPRESSION_GET:
|
|
85307
|
-
|
|
85154
|
+
plan = CreatePlan((LogicalExpressionGet &)op);
|
|
85155
|
+
break;
|
|
85308
85156
|
case LogicalOperatorType::LOGICAL_UPDATE:
|
|
85309
|
-
|
|
85157
|
+
plan = CreatePlan((LogicalUpdate &)op);
|
|
85158
|
+
break;
|
|
85310
85159
|
case LogicalOperatorType::LOGICAL_CREATE_TABLE:
|
|
85311
|
-
|
|
85160
|
+
plan = CreatePlan((LogicalCreateTable &)op);
|
|
85161
|
+
break;
|
|
85312
85162
|
case LogicalOperatorType::LOGICAL_CREATE_INDEX:
|
|
85313
|
-
|
|
85163
|
+
plan = CreatePlan((LogicalCreateIndex &)op);
|
|
85164
|
+
break;
|
|
85314
85165
|
case LogicalOperatorType::LOGICAL_EXPLAIN:
|
|
85315
|
-
|
|
85166
|
+
plan = CreatePlan((LogicalExplain &)op);
|
|
85167
|
+
break;
|
|
85316
85168
|
case LogicalOperatorType::LOGICAL_SHOW:
|
|
85317
|
-
|
|
85169
|
+
plan = CreatePlan((LogicalShow &)op);
|
|
85170
|
+
break;
|
|
85318
85171
|
case LogicalOperatorType::LOGICAL_DISTINCT:
|
|
85319
|
-
|
|
85172
|
+
plan = CreatePlan((LogicalDistinct &)op);
|
|
85173
|
+
break;
|
|
85320
85174
|
case LogicalOperatorType::LOGICAL_PREPARE:
|
|
85321
|
-
|
|
85175
|
+
plan = CreatePlan((LogicalPrepare &)op);
|
|
85176
|
+
break;
|
|
85322
85177
|
case LogicalOperatorType::LOGICAL_EXECUTE:
|
|
85323
|
-
|
|
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
|
-
|
|
85185
|
+
plan = CreatePlan((LogicalCreate &)op);
|
|
85186
|
+
break;
|
|
85330
85187
|
case LogicalOperatorType::LOGICAL_PRAGMA:
|
|
85331
|
-
|
|
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
|
-
|
|
85195
|
+
plan = CreatePlan((LogicalSimple &)op);
|
|
85196
|
+
break;
|
|
85338
85197
|
case LogicalOperatorType::LOGICAL_RECURSIVE_CTE:
|
|
85339
|
-
|
|
85198
|
+
plan = CreatePlan((LogicalRecursiveCTE &)op);
|
|
85199
|
+
break;
|
|
85340
85200
|
case LogicalOperatorType::LOGICAL_CTE_REF:
|
|
85341
|
-
|
|
85201
|
+
plan = CreatePlan((LogicalCTERef &)op);
|
|
85202
|
+
break;
|
|
85342
85203
|
case LogicalOperatorType::LOGICAL_EXPORT:
|
|
85343
|
-
|
|
85204
|
+
plan = CreatePlan((LogicalExport &)op);
|
|
85205
|
+
break;
|
|
85344
85206
|
case LogicalOperatorType::LOGICAL_SET:
|
|
85345
|
-
|
|
85346
|
-
|
|
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
|
-
|
|
144533
|
-
|
|
144534
|
-
|
|
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
|
-
|
|
144549
|
-
|
|
144550
|
-
|
|
144551
|
-
|
|
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
|
-
|
|
144554
|
-
|
|
144555
|
-
|
|
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
|
-
|
|
144560
|
-
|
|
144561
|
-
|
|
144562
|
-
|
|
145263
|
+
unique_ptr<EstimatedProperties> EstimatedProperties::Copy() {
|
|
145264
|
+
auto result = make_unique<EstimatedProperties>(cardinality, cost);
|
|
145265
|
+
return result;
|
|
145266
|
+
}
|
|
144563
145267
|
|
|
144564
|
-
|
|
145268
|
+
double JoinNode::GetCardinality() const {
|
|
145269
|
+
return estimated_props->GetCardinality();
|
|
145270
|
+
}
|
|
144565
145271
|
|
|
144566
|
-
|
|
144567
|
-
|
|
145272
|
+
double JoinNode::GetCost() {
|
|
145273
|
+
return estimated_props->GetCost();
|
|
145274
|
+
}
|
|
144568
145275
|
|
|
144569
|
-
|
|
144570
|
-
|
|
145276
|
+
void JoinNode::SetCost(double cost) {
|
|
145277
|
+
estimated_props->SetCost(cost);
|
|
145278
|
+
}
|
|
144571
145279
|
|
|
144572
|
-
|
|
144573
|
-
|
|
144574
|
-
|
|
144575
|
-
|
|
144576
|
-
|
|
144577
|
-
|
|
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
|
-
|
|
144584
|
-
|
|
144585
|
-
|
|
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
|
-
|
|
144596
|
-
|
|
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
|
|
144935
|
-
NeighborInfo
|
|
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
|
-
|
|
144939
|
-
return true;
|
|
145587
|
+
connections.push_back(info);
|
|
144940
145588
|
}
|
|
144941
145589
|
return false;
|
|
144942
145590
|
});
|
|
144943
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
144992
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
145297
|
-
|
|
145298
|
-
|
|
145299
|
-
//
|
|
145300
|
-
//
|
|
145301
|
-
|
|
145302
|
-
|
|
145303
|
-
|
|
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
|
|
145873
|
+
expected_cardinality = cardinality_estimator.EstimateCrossProduct(left, right);
|
|
145306
145874
|
} else {
|
|
145307
145875
|
// normal join, expect foreign key join
|
|
145308
|
-
expected_cardinality =
|
|
145876
|
+
expected_cardinality = cardinality_estimator.EstimateCardinalityWithSet(set);
|
|
145877
|
+
best_connection = possible_connections.back();
|
|
145309
145878
|
}
|
|
145310
|
-
|
|
145311
|
-
|
|
145312
|
-
|
|
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
|
-
|
|
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->
|
|
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,
|
|
145942
|
+
bool JoinOrderOptimizer::TryEmitPair(JoinRelationSet *left, JoinRelationSet *right,
|
|
145943
|
+
const vector<NeighborInfo *> &info) {
|
|
145334
145944
|
pairs++;
|
|
145335
|
-
|
|
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
|
-
|
|
145361
|
-
|
|
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
|
|
145367
|
-
if (
|
|
145368
|
-
if (!TryEmitPair(node, neighbor_relation,
|
|
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
|
|
145394
|
-
if (
|
|
145395
|
-
if (!TryEmitPair(left, combined_set,
|
|
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
|
|
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
|
-
//
|
|
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.
|
|
145489
|
-
if (connection) {
|
|
145490
|
-
// we can
|
|
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
|
-
|
|
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]->
|
|
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
|
|
145529
|
-
D_ASSERT(
|
|
146246
|
+
auto connections = query_graph.GetConnections(left, right);
|
|
146247
|
+
D_ASSERT(!connections.empty());
|
|
145530
146248
|
|
|
145531
|
-
best_connection = EmitPair(left, right,
|
|
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
|
-
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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
|
-
|
|
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)
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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 #
|
|
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
|