duckdb 0.4.1-dev723.0 → 0.4.1-dev752.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 +230 -124
- package/src/duckdb.hpp +16 -9
- package/src/parquet-amalgamation.cpp +28270 -28270
package/src/duckdb.cpp
CHANGED
|
@@ -978,8 +978,10 @@ LogicalType Catalog::GetType(ClientContext &context, const string &schema, const
|
|
|
978
978
|
|
|
979
979
|
void Catalog::Alter(ClientContext &context, AlterInfo *info) {
|
|
980
980
|
ModifyCatalog();
|
|
981
|
-
auto lookup = LookupEntry(context, info->GetCatalogType(), info->schema, info->name);
|
|
982
|
-
|
|
981
|
+
auto lookup = LookupEntry(context, info->GetCatalogType(), info->schema, info->name, info->if_exists);
|
|
982
|
+
if (!lookup.Found()) {
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
983
985
|
return lookup.schema->Alter(context, info);
|
|
984
986
|
}
|
|
985
987
|
|
|
@@ -20486,7 +20488,7 @@ std::string NumericHelper::ToString(hugeint_t value);
|
|
|
20486
20488
|
|
|
20487
20489
|
struct DecimalToString {
|
|
20488
20490
|
template <class SIGNED, class UNSIGNED>
|
|
20489
|
-
static int DecimalLength(SIGNED value, uint8_t scale) {
|
|
20491
|
+
static int DecimalLength(SIGNED value, uint8_t width, uint8_t scale) {
|
|
20490
20492
|
if (scale == 0) {
|
|
20491
20493
|
// scale is 0: regular number
|
|
20492
20494
|
return NumericHelper::SignedLength<SIGNED, UNSIGNED>(value);
|
|
@@ -20498,11 +20500,13 @@ struct DecimalToString {
|
|
|
20498
20500
|
// in that case we print "0.XXX", which is the scale, plus "0." (2 chars)
|
|
20499
20501
|
// integer length + 1 happens when the number is outside of that range
|
|
20500
20502
|
// in that case we print the integer number, but with one extra character ('.')
|
|
20501
|
-
|
|
20503
|
+
auto extra_characters = width > scale ? 2 : 1;
|
|
20504
|
+
return MaxValue(scale + extra_characters + (value < 0 ? 1 : 0),
|
|
20505
|
+
NumericHelper::SignedLength<SIGNED, UNSIGNED>(value) + 1);
|
|
20502
20506
|
}
|
|
20503
20507
|
|
|
20504
20508
|
template <class SIGNED, class UNSIGNED>
|
|
20505
|
-
static void FormatDecimal(SIGNED value, uint8_t scale, char *dst, idx_t len) {
|
|
20509
|
+
static void FormatDecimal(SIGNED value, uint8_t width, uint8_t scale, char *dst, idx_t len) {
|
|
20506
20510
|
char *end = dst + len;
|
|
20507
20511
|
if (value < 0) {
|
|
20508
20512
|
value = -value;
|
|
@@ -20525,14 +20529,18 @@ struct DecimalToString {
|
|
|
20525
20529
|
}
|
|
20526
20530
|
*--dst = '.';
|
|
20527
20531
|
// now write the part before the decimal
|
|
20528
|
-
|
|
20532
|
+
D_ASSERT(width > scale || major == 0);
|
|
20533
|
+
if (width > scale) {
|
|
20534
|
+
// there are numbers after the comma
|
|
20535
|
+
dst = NumericHelper::FormatUnsigned<UNSIGNED>(major, dst);
|
|
20536
|
+
}
|
|
20529
20537
|
}
|
|
20530
20538
|
|
|
20531
20539
|
template <class SIGNED, class UNSIGNED>
|
|
20532
|
-
static string_t Format(SIGNED value, uint8_t scale, Vector &vector) {
|
|
20533
|
-
int len = DecimalLength<SIGNED, UNSIGNED>(value, scale);
|
|
20540
|
+
static string_t Format(SIGNED value, uint8_t width, uint8_t scale, Vector &vector) {
|
|
20541
|
+
int len = DecimalLength<SIGNED, UNSIGNED>(value, width, scale);
|
|
20534
20542
|
string_t result = StringVector::EmptyString(vector, len);
|
|
20535
|
-
FormatDecimal<SIGNED, UNSIGNED>(value, scale, result.GetDataWriteable(), len);
|
|
20543
|
+
FormatDecimal<SIGNED, UNSIGNED>(value, width, scale, result.GetDataWriteable(), len);
|
|
20536
20544
|
result.Finalize();
|
|
20537
20545
|
return result;
|
|
20538
20546
|
}
|
|
@@ -20655,7 +20663,7 @@ struct HugeintToStringCast {
|
|
|
20655
20663
|
return result;
|
|
20656
20664
|
}
|
|
20657
20665
|
|
|
20658
|
-
static int DecimalLength(hugeint_t value, uint8_t scale) {
|
|
20666
|
+
static int DecimalLength(hugeint_t value, uint8_t width, uint8_t scale) {
|
|
20659
20667
|
int negative;
|
|
20660
20668
|
if (value.upper < 0) {
|
|
20661
20669
|
Hugeint::NegateInPlace(value);
|
|
@@ -20674,10 +20682,11 @@ struct HugeintToStringCast {
|
|
|
20674
20682
|
// in that case we print "0.XXX", which is the scale, plus "0." (2 chars)
|
|
20675
20683
|
// integer length + 1 happens when the number is outside of that range
|
|
20676
20684
|
// in that case we print the integer number, but with one extra character ('.')
|
|
20677
|
-
|
|
20685
|
+
auto extra_numbers = width > scale ? 2 : 1;
|
|
20686
|
+
return MaxValue(scale + extra_numbers, UnsignedLength(value) + 1) + negative;
|
|
20678
20687
|
}
|
|
20679
20688
|
|
|
20680
|
-
static void FormatDecimal(hugeint_t value, uint8_t scale, char *dst, int len) {
|
|
20689
|
+
static void FormatDecimal(hugeint_t value, uint8_t width, uint8_t scale, char *dst, int len) {
|
|
20681
20690
|
auto endptr = dst + len;
|
|
20682
20691
|
|
|
20683
20692
|
int negative = value.upper < 0;
|
|
@@ -20706,16 +20715,19 @@ struct HugeintToStringCast {
|
|
|
20706
20715
|
}
|
|
20707
20716
|
*--dst = '.';
|
|
20708
20717
|
// now write the part before the decimal
|
|
20709
|
-
|
|
20718
|
+
D_ASSERT(width > scale || major == 0);
|
|
20719
|
+
if (width > scale) {
|
|
20720
|
+
dst = FormatUnsigned(major, dst);
|
|
20721
|
+
}
|
|
20710
20722
|
}
|
|
20711
20723
|
|
|
20712
|
-
static string_t FormatDecimal(hugeint_t value, uint8_t scale, Vector &vector) {
|
|
20713
|
-
int length = DecimalLength(value, scale);
|
|
20724
|
+
static string_t FormatDecimal(hugeint_t value, uint8_t width, uint8_t scale, Vector &vector) {
|
|
20725
|
+
int length = DecimalLength(value, width, scale);
|
|
20714
20726
|
string_t result = StringVector::EmptyString(vector, length);
|
|
20715
20727
|
|
|
20716
20728
|
auto dst = result.GetDataWriteable();
|
|
20717
20729
|
|
|
20718
|
-
FormatDecimal(value, scale, dst, length);
|
|
20730
|
+
FormatDecimal(value, width, scale, dst, length);
|
|
20719
20731
|
|
|
20720
20732
|
result.Finalize();
|
|
20721
20733
|
return result;
|
|
@@ -24984,22 +24996,22 @@ bool TryCastToDecimal::Operation(string_t input, hugeint_t &result, string *erro
|
|
|
24984
24996
|
|
|
24985
24997
|
template <>
|
|
24986
24998
|
string_t StringCastFromDecimal::Operation(int16_t input, uint8_t width, uint8_t scale, Vector &result) {
|
|
24987
|
-
return DecimalToString::Format<int16_t, uint16_t>(input, scale, result);
|
|
24999
|
+
return DecimalToString::Format<int16_t, uint16_t>(input, width, scale, result);
|
|
24988
25000
|
}
|
|
24989
25001
|
|
|
24990
25002
|
template <>
|
|
24991
25003
|
string_t StringCastFromDecimal::Operation(int32_t input, uint8_t width, uint8_t scale, Vector &result) {
|
|
24992
|
-
return DecimalToString::Format<int32_t, uint32_t>(input, scale, result);
|
|
25004
|
+
return DecimalToString::Format<int32_t, uint32_t>(input, width, scale, result);
|
|
24993
25005
|
}
|
|
24994
25006
|
|
|
24995
25007
|
template <>
|
|
24996
25008
|
string_t StringCastFromDecimal::Operation(int64_t input, uint8_t width, uint8_t scale, Vector &result) {
|
|
24997
|
-
return DecimalToString::Format<int64_t, uint64_t>(input, scale, result);
|
|
25009
|
+
return DecimalToString::Format<int64_t, uint64_t>(input, width, scale, result);
|
|
24998
25010
|
}
|
|
24999
25011
|
|
|
25000
25012
|
template <>
|
|
25001
25013
|
string_t StringCastFromDecimal::Operation(hugeint_t input, uint8_t width, uint8_t scale, Vector &result) {
|
|
25002
|
-
return HugeintToStringCast::FormatDecimal(input, scale, result);
|
|
25014
|
+
return HugeintToStringCast::FormatDecimal(input, width, scale, result);
|
|
25003
25015
|
}
|
|
25004
25016
|
|
|
25005
25017
|
//===--------------------------------------------------------------------===//
|
|
@@ -39884,29 +39896,29 @@ date_t Date::GetMondayOfCurrentWeek(date_t date) {
|
|
|
39884
39896
|
namespace duckdb {
|
|
39885
39897
|
|
|
39886
39898
|
template <class SIGNED, class UNSIGNED>
|
|
39887
|
-
string TemplatedDecimalToString(SIGNED value, uint8_t scale) {
|
|
39888
|
-
auto len = DecimalToString::DecimalLength<SIGNED, UNSIGNED>(value, scale);
|
|
39899
|
+
string TemplatedDecimalToString(SIGNED value, uint8_t width, uint8_t scale) {
|
|
39900
|
+
auto len = DecimalToString::DecimalLength<SIGNED, UNSIGNED>(value, width, scale);
|
|
39889
39901
|
auto data = unique_ptr<char[]>(new char[len + 1]);
|
|
39890
|
-
DecimalToString::FormatDecimal<SIGNED, UNSIGNED>(value, scale, data.get(), len);
|
|
39902
|
+
DecimalToString::FormatDecimal<SIGNED, UNSIGNED>(value, width, scale, data.get(), len);
|
|
39891
39903
|
return string(data.get(), len);
|
|
39892
39904
|
}
|
|
39893
39905
|
|
|
39894
|
-
string Decimal::ToString(int16_t value, uint8_t scale) {
|
|
39895
|
-
return TemplatedDecimalToString<int16_t, uint16_t>(value, scale);
|
|
39906
|
+
string Decimal::ToString(int16_t value, uint8_t width, uint8_t scale) {
|
|
39907
|
+
return TemplatedDecimalToString<int16_t, uint16_t>(value, width, scale);
|
|
39896
39908
|
}
|
|
39897
39909
|
|
|
39898
|
-
string Decimal::ToString(int32_t value, uint8_t scale) {
|
|
39899
|
-
return TemplatedDecimalToString<int32_t, uint32_t>(value, scale);
|
|
39910
|
+
string Decimal::ToString(int32_t value, uint8_t width, uint8_t scale) {
|
|
39911
|
+
return TemplatedDecimalToString<int32_t, uint32_t>(value, width, scale);
|
|
39900
39912
|
}
|
|
39901
39913
|
|
|
39902
|
-
string Decimal::ToString(int64_t value, uint8_t scale) {
|
|
39903
|
-
return TemplatedDecimalToString<int64_t, uint64_t>(value, scale);
|
|
39914
|
+
string Decimal::ToString(int64_t value, uint8_t width, uint8_t scale) {
|
|
39915
|
+
return TemplatedDecimalToString<int64_t, uint64_t>(value, width, scale);
|
|
39904
39916
|
}
|
|
39905
39917
|
|
|
39906
|
-
string Decimal::ToString(hugeint_t value, uint8_t scale) {
|
|
39907
|
-
auto len = HugeintToStringCast::DecimalLength(value, scale);
|
|
39918
|
+
string Decimal::ToString(hugeint_t value, uint8_t width, uint8_t scale) {
|
|
39919
|
+
auto len = HugeintToStringCast::DecimalLength(value, width, scale);
|
|
39908
39920
|
auto data = unique_ptr<char[]>(new char[len + 1]);
|
|
39909
|
-
HugeintToStringCast::FormatDecimal(value, scale, data.get(), len);
|
|
39921
|
+
HugeintToStringCast::FormatDecimal(value, width, scale, data.get(), len);
|
|
39910
39922
|
return string(data.get(), len);
|
|
39911
39923
|
}
|
|
39912
39924
|
|
|
@@ -44714,16 +44726,17 @@ string Value::ToString() const {
|
|
|
44714
44726
|
return duckdb_fmt::format("{}", value_.double_);
|
|
44715
44727
|
case LogicalTypeId::DECIMAL: {
|
|
44716
44728
|
auto internal_type = type_.InternalType();
|
|
44729
|
+
auto width = DecimalType::GetWidth(type_);
|
|
44717
44730
|
auto scale = DecimalType::GetScale(type_);
|
|
44718
44731
|
if (internal_type == PhysicalType::INT16) {
|
|
44719
|
-
return Decimal::ToString(value_.smallint, scale);
|
|
44732
|
+
return Decimal::ToString(value_.smallint, width, scale);
|
|
44720
44733
|
} else if (internal_type == PhysicalType::INT32) {
|
|
44721
|
-
return Decimal::ToString(value_.integer, scale);
|
|
44734
|
+
return Decimal::ToString(value_.integer, width, scale);
|
|
44722
44735
|
} else if (internal_type == PhysicalType::INT64) {
|
|
44723
|
-
return Decimal::ToString(value_.bigint, scale);
|
|
44736
|
+
return Decimal::ToString(value_.bigint, width, scale);
|
|
44724
44737
|
} else {
|
|
44725
44738
|
D_ASSERT(internal_type == PhysicalType::INT128);
|
|
44726
|
-
return Decimal::ToString(value_.hugeint, scale);
|
|
44739
|
+
return Decimal::ToString(value_.hugeint, width, scale);
|
|
44727
44740
|
}
|
|
44728
44741
|
}
|
|
44729
44742
|
case LogicalTypeId::DATE:
|
|
@@ -50705,9 +50718,9 @@ struct DecimalScaleInput {
|
|
|
50705
50718
|
DecimalScaleInput(Vector &result_p, FACTOR_TYPE factor_p) : result(result_p), factor(factor_p) {
|
|
50706
50719
|
}
|
|
50707
50720
|
DecimalScaleInput(Vector &result_p, LIMIT_TYPE limit_p, FACTOR_TYPE factor_p, string *error_message_p,
|
|
50708
|
-
uint8_t source_scale_p)
|
|
50721
|
+
uint8_t source_width_p, uint8_t source_scale_p)
|
|
50709
50722
|
: result(result_p), limit(limit_p), factor(factor_p), error_message(error_message_p),
|
|
50710
|
-
source_scale(source_scale_p) {
|
|
50723
|
+
source_width(source_width_p), source_scale(source_scale_p) {
|
|
50711
50724
|
}
|
|
50712
50725
|
|
|
50713
50726
|
Vector &result;
|
|
@@ -50715,6 +50728,7 @@ struct DecimalScaleInput {
|
|
|
50715
50728
|
FACTOR_TYPE factor;
|
|
50716
50729
|
bool all_converted = true;
|
|
50717
50730
|
string *error_message;
|
|
50731
|
+
uint8_t source_width;
|
|
50718
50732
|
uint8_t source_scale;
|
|
50719
50733
|
};
|
|
50720
50734
|
|
|
@@ -50731,9 +50745,9 @@ struct DecimalScaleUpCheckOperator {
|
|
|
50731
50745
|
static RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) {
|
|
50732
50746
|
auto data = (DecimalScaleInput<INPUT_TYPE, RESULT_TYPE> *)dataptr;
|
|
50733
50747
|
if (input >= data->limit || input <= -data->limit) {
|
|
50734
|
-
auto error =
|
|
50735
|
-
|
|
50736
|
-
|
|
50748
|
+
auto error = StringUtil::Format("Casting value \"%s\" to type %s failed: value is out of range!",
|
|
50749
|
+
Decimal::ToString(input, data->source_width, data->source_scale),
|
|
50750
|
+
data->result.GetType().ToString());
|
|
50737
50751
|
return HandleVectorCastError::Operation<RESULT_TYPE>(move(error), mask, idx, data->error_message,
|
|
50738
50752
|
data->all_converted);
|
|
50739
50753
|
}
|
|
@@ -50759,7 +50773,8 @@ bool TemplatedDecimalScaleUp(Vector &source, Vector &result, idx_t count, string
|
|
|
50759
50773
|
} else {
|
|
50760
50774
|
// type might not fit: check limit
|
|
50761
50775
|
auto limit = POWERS_SOURCE::POWERS_OF_TEN[target_width];
|
|
50762
|
-
DecimalScaleInput<SOURCE, DEST> input(result, limit, multiply_factor, error_message,
|
|
50776
|
+
DecimalScaleInput<SOURCE, DEST> input(result, limit, multiply_factor, error_message, source_width,
|
|
50777
|
+
source_scale);
|
|
50763
50778
|
UnaryExecutor::GenericExecute<SOURCE, DEST, DecimalScaleUpCheckOperator>(source, result, count, &input,
|
|
50764
50779
|
error_message);
|
|
50765
50780
|
return input.all_converted;
|
|
@@ -50779,9 +50794,9 @@ struct DecimalScaleDownCheckOperator {
|
|
|
50779
50794
|
static RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) {
|
|
50780
50795
|
auto data = (DecimalScaleInput<INPUT_TYPE> *)dataptr;
|
|
50781
50796
|
if (input >= data->limit || input <= -data->limit) {
|
|
50782
|
-
auto error =
|
|
50783
|
-
|
|
50784
|
-
|
|
50797
|
+
auto error = StringUtil::Format("Casting value \"%s\" to type %s failed: value is out of range!",
|
|
50798
|
+
Decimal::ToString(input, data->source_width, data->source_scale),
|
|
50799
|
+
data->result.GetType().ToString());
|
|
50785
50800
|
return HandleVectorCastError::Operation<RESULT_TYPE>(move(error), mask, idx, data->error_message,
|
|
50786
50801
|
data->all_converted);
|
|
50787
50802
|
}
|
|
@@ -50807,7 +50822,7 @@ bool TemplatedDecimalScaleDown(Vector &source, Vector &result, idx_t count, stri
|
|
|
50807
50822
|
} else {
|
|
50808
50823
|
// type might not fit: check limit
|
|
50809
50824
|
auto limit = POWERS_SOURCE::POWERS_OF_TEN[target_width];
|
|
50810
|
-
DecimalScaleInput<SOURCE> input(result, limit, divide_factor, error_message, source_scale);
|
|
50825
|
+
DecimalScaleInput<SOURCE> input(result, limit, divide_factor, error_message, source_width, source_scale);
|
|
50811
50826
|
UnaryExecutor::GenericExecute<SOURCE, DEST, DecimalScaleDownCheckOperator>(source, result, count, &input,
|
|
50812
50827
|
error_message);
|
|
50813
50828
|
return input.all_converted;
|
|
@@ -55199,8 +55214,8 @@ void ExpressionExecutor::ExecuteExpression(idx_t expr_idx, Vector &result) {
|
|
|
55199
55214
|
states[expr_idx]->profiler.EndSample(chunk ? chunk->size() : 0);
|
|
55200
55215
|
}
|
|
55201
55216
|
|
|
55202
|
-
Value ExpressionExecutor::EvaluateScalar(const Expression &expr) {
|
|
55203
|
-
D_ASSERT(expr.IsFoldable());
|
|
55217
|
+
Value ExpressionExecutor::EvaluateScalar(const Expression &expr, bool allow_unfoldable) {
|
|
55218
|
+
D_ASSERT(allow_unfoldable || expr.IsFoldable());
|
|
55204
55219
|
D_ASSERT(expr.IsScalar());
|
|
55205
55220
|
// use an ExpressionExecutor to execute the expression
|
|
55206
55221
|
ExpressionExecutor executor(Allocator::DefaultAllocator(), expr);
|
|
@@ -55208,7 +55223,7 @@ Value ExpressionExecutor::EvaluateScalar(const Expression &expr) {
|
|
|
55208
55223
|
Vector result(expr.return_type);
|
|
55209
55224
|
executor.ExecuteExpression(result);
|
|
55210
55225
|
|
|
55211
|
-
D_ASSERT(result.GetVectorType() == VectorType::CONSTANT_VECTOR);
|
|
55226
|
+
D_ASSERT(allow_unfoldable || result.GetVectorType() == VectorType::CONSTANT_VECTOR);
|
|
55212
55227
|
auto result_value = result.GetValue(0);
|
|
55213
55228
|
D_ASSERT(result_value.type().InternalType() == expr.return_type.InternalType());
|
|
55214
55229
|
return result_value;
|
|
@@ -62938,7 +62953,15 @@ void PhysicalLimitPercent::GetData(ExecutionContext &context, DataChunk &chunk,
|
|
|
62938
62953
|
if (count > 0) {
|
|
62939
62954
|
count += offset;
|
|
62940
62955
|
}
|
|
62941
|
-
|
|
62956
|
+
if (limit_percent < 0 || limit_percent > 100) {
|
|
62957
|
+
throw OutOfRangeException("Limit percent out of range, should be between 0% and 100%");
|
|
62958
|
+
}
|
|
62959
|
+
double limit_dbl = limit_percent / 100 * count;
|
|
62960
|
+
if (limit_dbl > count) {
|
|
62961
|
+
limit = count;
|
|
62962
|
+
} else {
|
|
62963
|
+
limit = idx_t(limit_dbl);
|
|
62964
|
+
}
|
|
62942
62965
|
if (limit == 0) {
|
|
62943
62966
|
return;
|
|
62944
62967
|
}
|
|
@@ -63920,9 +63943,6 @@ public:
|
|
|
63920
63943
|
|
|
63921
63944
|
unique_ptr<VacuumInfo> info;
|
|
63922
63945
|
|
|
63923
|
-
private:
|
|
63924
|
-
unordered_map<idx_t, idx_t> column_id_map;
|
|
63925
|
-
|
|
63926
63946
|
public:
|
|
63927
63947
|
// Source interface
|
|
63928
63948
|
void GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate,
|
|
@@ -64065,12 +64085,6 @@ namespace duckdb {
|
|
|
64065
64085
|
PhysicalVacuum::PhysicalVacuum(unique_ptr<VacuumInfo> info_p, idx_t estimated_cardinality)
|
|
64066
64086
|
: PhysicalOperator(PhysicalOperatorType::VACUUM, {LogicalType::BOOLEAN}, estimated_cardinality),
|
|
64067
64087
|
info(move(info_p)) {
|
|
64068
|
-
if (info->has_table) {
|
|
64069
|
-
auto &get = (LogicalGet &)*info->bound_ref->get;
|
|
64070
|
-
for (idx_t i = 0; i < get.column_ids.size(); i++) {
|
|
64071
|
-
column_id_map[i] = get.column_ids[i];
|
|
64072
|
-
}
|
|
64073
|
-
}
|
|
64074
64088
|
}
|
|
64075
64089
|
|
|
64076
64090
|
class VacuumLocalSinkState : public LocalSinkState {
|
|
@@ -64107,7 +64121,7 @@ unique_ptr<GlobalSinkState> PhysicalVacuum::GetGlobalSinkState(ClientContext &co
|
|
|
64107
64121
|
SinkResultType PhysicalVacuum::Sink(ExecutionContext &context, GlobalSinkState &gstate_p, LocalSinkState &lstate_p,
|
|
64108
64122
|
DataChunk &input) const {
|
|
64109
64123
|
auto &lstate = (VacuumLocalSinkState &)lstate_p;
|
|
64110
|
-
D_ASSERT(lstate.column_distinct_stats.size() == column_id_map.size());
|
|
64124
|
+
D_ASSERT(lstate.column_distinct_stats.size() == info->column_id_map.size());
|
|
64111
64125
|
|
|
64112
64126
|
for (idx_t col_idx = 0; col_idx < input.data.size(); col_idx++) {
|
|
64113
64127
|
lstate.column_distinct_stats[col_idx]->Update(input.data[col_idx], input.size(), false);
|
|
@@ -64131,9 +64145,9 @@ SinkFinalizeType PhysicalVacuum::Finalize(Pipeline &pipeline, Event &event, Clie
|
|
|
64131
64145
|
GlobalSinkState &gstate) const {
|
|
64132
64146
|
auto &sink = (VacuumGlobalSinkState &)gstate;
|
|
64133
64147
|
|
|
64134
|
-
auto table = info->
|
|
64148
|
+
auto table = info->table;
|
|
64135
64149
|
for (idx_t col_idx = 0; col_idx < sink.column_distinct_stats.size(); col_idx++) {
|
|
64136
|
-
table->storage->SetStatistics(column_id_map.at(col_idx), [&](BaseStatistics &stats) {
|
|
64150
|
+
table->storage->SetStatistics(info->column_id_map.at(col_idx), [&](BaseStatistics &stats) {
|
|
64137
64151
|
stats.distinct_stats = move(sink.column_distinct_stats[col_idx]);
|
|
64138
64152
|
});
|
|
64139
64153
|
}
|
|
@@ -76551,6 +76565,16 @@ void CheckForPerfectJoinOpt(LogicalComparisonJoin &op, PerfectHashJoinStats &joi
|
|
|
76551
76565
|
if (op.join_stats.empty()) {
|
|
76552
76566
|
return;
|
|
76553
76567
|
}
|
|
76568
|
+
for (auto &type : op.children[1]->types) {
|
|
76569
|
+
switch (type.id()) {
|
|
76570
|
+
case LogicalTypeId::STRUCT:
|
|
76571
|
+
case LogicalTypeId::LIST:
|
|
76572
|
+
case LogicalTypeId::MAP:
|
|
76573
|
+
return;
|
|
76574
|
+
default:
|
|
76575
|
+
break;
|
|
76576
|
+
}
|
|
76577
|
+
}
|
|
76554
76578
|
// with equality condition and null values not equal
|
|
76555
76579
|
for (auto &&condition : op.conditions) {
|
|
76556
76580
|
if (condition.comparison != ExpressionType::COMPARE_EQUAL) {
|
|
@@ -79202,16 +79226,12 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalSimple &op
|
|
|
79202
79226
|
return make_unique<PhysicalTransaction>(unique_ptr_cast<ParseInfo, TransactionInfo>(move(op.info)),
|
|
79203
79227
|
op.estimated_cardinality);
|
|
79204
79228
|
case LogicalOperatorType::LOGICAL_VACUUM: {
|
|
79205
|
-
auto &info = (VacuumInfo &)*op.info;
|
|
79206
|
-
if (!info.has_table) {
|
|
79207
|
-
return make_unique<PhysicalVacuum>(unique_ptr_cast<ParseInfo, VacuumInfo>(move(op.info)),
|
|
79208
|
-
op.estimated_cardinality);
|
|
79209
|
-
}
|
|
79210
|
-
info.bound_ref->get->ResolveOperatorTypes();
|
|
79211
|
-
auto child = CreatePlan(*info.bound_ref->get);
|
|
79212
79229
|
auto result = make_unique<PhysicalVacuum>(unique_ptr_cast<ParseInfo, VacuumInfo>(move(op.info)),
|
|
79213
79230
|
op.estimated_cardinality);
|
|
79214
|
-
|
|
79231
|
+
if (!op.children.empty()) {
|
|
79232
|
+
auto child = CreatePlan(*op.children[0]);
|
|
79233
|
+
result->children.push_back(move(child));
|
|
79234
|
+
}
|
|
79215
79235
|
return move(result);
|
|
79216
79236
|
}
|
|
79217
79237
|
case LogicalOperatorType::LOGICAL_LOAD:
|
|
@@ -79471,21 +79491,18 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalWindow &op
|
|
|
79471
79491
|
types.resize(output_idx);
|
|
79472
79492
|
|
|
79473
79493
|
// Identify streaming windows
|
|
79474
|
-
vector<idx_t>
|
|
79475
|
-
|
|
79494
|
+
vector<idx_t> window_expressions;
|
|
79495
|
+
bool process_streaming = true;
|
|
79476
79496
|
for (idx_t expr_idx = 0; expr_idx < op.expressions.size(); expr_idx++) {
|
|
79477
|
-
|
|
79478
|
-
|
|
79479
|
-
|
|
79480
|
-
blocking_windows.push_back(expr_idx);
|
|
79497
|
+
window_expressions.push_back(expr_idx);
|
|
79498
|
+
if (!IsStreamingWindow(op.expressions[expr_idx])) {
|
|
79499
|
+
process_streaming = false;
|
|
79481
79500
|
}
|
|
79482
79501
|
}
|
|
79483
|
-
|
|
79484
79502
|
// Process the window functions by sharing the partition/order definitions
|
|
79485
79503
|
vector<idx_t> evaluation_order;
|
|
79486
|
-
while (!
|
|
79487
|
-
|
|
79488
|
-
auto &remaining = process_streaming ? streaming_windows : blocking_windows;
|
|
79504
|
+
while (!window_expressions.empty()) {
|
|
79505
|
+
auto &remaining = window_expressions;
|
|
79489
79506
|
|
|
79490
79507
|
// Find all functions that share the partitioning of the first remaining expression
|
|
79491
79508
|
const auto over_idx = remaining[0];
|
|
@@ -80067,7 +80084,7 @@ void RadixPartitionedHashTable::GetData(ExecutionContext &context, DataChunk &ch
|
|
|
80067
80084
|
// special case hack to sort out aggregating from empty intermediates
|
|
80068
80085
|
// for aggregations without groups
|
|
80069
80086
|
if (gstate.is_empty && grouping_set.empty()) {
|
|
80070
|
-
D_ASSERT(chunk.ColumnCount() == null_groups.size() + op.aggregates.size());
|
|
80087
|
+
D_ASSERT(chunk.ColumnCount() == null_groups.size() + op.aggregates.size() + op.grouping_functions.size());
|
|
80071
80088
|
// for each column in the aggregates, set to initial state
|
|
80072
80089
|
chunk.SetCardinality(1);
|
|
80073
80090
|
for (auto null_group : null_groups) {
|
|
@@ -80087,6 +80104,9 @@ void RadixPartitionedHashTable::GetData(ExecutionContext &context, DataChunk &ch
|
|
|
80087
80104
|
aggr.function.destructor(state_vector, 1);
|
|
80088
80105
|
}
|
|
80089
80106
|
}
|
|
80107
|
+
for (idx_t i = 0; i < op.grouping_functions.size(); i++) {
|
|
80108
|
+
chunk.data[null_groups.size() + op.aggregates.size() + i].Reference(grouping_values[i]);
|
|
80109
|
+
}
|
|
80090
80110
|
state.finished = true;
|
|
80091
80111
|
return;
|
|
80092
80112
|
}
|
|
@@ -103472,6 +103492,9 @@ static unique_ptr<FunctionData> LikeBindFunction(ClientContext &context, ScalarF
|
|
|
103472
103492
|
D_ASSERT(arguments.size() == 2 || arguments.size() == 3);
|
|
103473
103493
|
if (arguments[1]->IsFoldable()) {
|
|
103474
103494
|
Value pattern_str = ExpressionExecutor::EvaluateScalar(*arguments[1]);
|
|
103495
|
+
if (pattern_str.IsNull()) {
|
|
103496
|
+
return nullptr;
|
|
103497
|
+
}
|
|
103475
103498
|
return LikeMatcher::CreateLikeMatcher(pattern_str.ToString());
|
|
103476
103499
|
}
|
|
103477
103500
|
return nullptr;
|
|
@@ -105818,6 +105841,9 @@ static void StructExtractFunction(DataChunk &args, ExpressionState &state, Vecto
|
|
|
105818
105841
|
static unique_ptr<FunctionData> StructExtractBind(ClientContext &context, ScalarFunction &bound_function,
|
|
105819
105842
|
vector<unique_ptr<Expression>> &arguments) {
|
|
105820
105843
|
D_ASSERT(bound_function.arguments.size() == 2);
|
|
105844
|
+
if (arguments[0]->return_type.id() == LogicalTypeId::UNKNOWN) {
|
|
105845
|
+
throw ParameterNotResolvedException();
|
|
105846
|
+
}
|
|
105821
105847
|
D_ASSERT(LogicalTypeId::STRUCT == arguments[0]->return_type.id());
|
|
105822
105848
|
auto &struct_children = StructType::GetChildTypes(arguments[0]->return_type);
|
|
105823
105849
|
if (struct_children.empty()) {
|
|
@@ -117754,7 +117780,14 @@ unique_ptr<PendingQueryResult> ClientContext::PendingStatementInternal(ClientCon
|
|
|
117754
117780
|
unique_ptr<SQLStatement> statement,
|
|
117755
117781
|
PendingQueryParameters parameters) {
|
|
117756
117782
|
// prepare the query for execution
|
|
117757
|
-
auto prepared = CreatePreparedStatement(lock, query, move(statement));
|
|
117783
|
+
auto prepared = CreatePreparedStatement(lock, query, move(statement), parameters.parameters);
|
|
117784
|
+
if (prepared->properties.parameter_count > 0 && !parameters.parameters) {
|
|
117785
|
+
return make_unique<PendingQueryResult>(StringUtil::Format("Expected %lld parameters, but none were supplied",
|
|
117786
|
+
prepared->properties.parameter_count));
|
|
117787
|
+
}
|
|
117788
|
+
if (!prepared->properties.bound_all_parameters) {
|
|
117789
|
+
return make_unique<PendingQueryResult>("Not all parameters were bound");
|
|
117790
|
+
}
|
|
117758
117791
|
// execute the prepared statement
|
|
117759
117792
|
return PendingPreparedStatement(lock, move(prepared), parameters);
|
|
117760
117793
|
}
|
|
@@ -138716,7 +138749,7 @@ unique_ptr<LogicalOperator> FilterPushdown::PushdownCrossProduct(unique_ptr<Logi
|
|
|
138716
138749
|
// bindings match right side: push into right
|
|
138717
138750
|
right_pushdown.filters.push_back(move(f));
|
|
138718
138751
|
} else {
|
|
138719
|
-
D_ASSERT(side == JoinSide::BOTH);
|
|
138752
|
+
D_ASSERT(side == JoinSide::BOTH || side == JoinSide::NONE);
|
|
138720
138753
|
// bindings match both: turn into join condition
|
|
138721
138754
|
join_conditions.push_back(move(f->filter));
|
|
138722
138755
|
}
|
|
@@ -139604,23 +139637,6 @@ void RemoveUnusedColumns::VisitOperator(LogicalOperator &op) {
|
|
|
139604
139637
|
everything_referenced = true;
|
|
139605
139638
|
break;
|
|
139606
139639
|
}
|
|
139607
|
-
case LogicalOperatorType::LOGICAL_VACUUM: {
|
|
139608
|
-
auto &vacuum = (LogicalSimple &)op;
|
|
139609
|
-
auto &info = (VacuumInfo &)*vacuum.info;
|
|
139610
|
-
if (!info.bound_ref) {
|
|
139611
|
-
break;
|
|
139612
|
-
}
|
|
139613
|
-
|
|
139614
|
-
auto &get = (LogicalGet &)*info.bound_ref->get;
|
|
139615
|
-
for (auto &col : info.columns) {
|
|
139616
|
-
for (idx_t col_idx = 0; col_idx < get.names.size(); col_idx++) {
|
|
139617
|
-
if (get.names[col_idx] == col) {
|
|
139618
|
-
get.column_ids.push_back(col_idx);
|
|
139619
|
-
break;
|
|
139620
|
-
}
|
|
139621
|
-
}
|
|
139622
|
-
}
|
|
139623
|
-
}
|
|
139624
139640
|
default:
|
|
139625
139641
|
break;
|
|
139626
139642
|
}
|
|
@@ -150987,7 +151003,7 @@ string KeywordHelper::WriteOptionallyQuoted(const string &text, char quote) {
|
|
|
150987
151003
|
namespace duckdb {
|
|
150988
151004
|
|
|
150989
151005
|
AlterInfo::AlterInfo(AlterType type, string schema_p, string name_p)
|
|
150990
|
-
: type(type), schema(move(schema_p)), name(move(name_p)) {
|
|
151006
|
+
: type(type), if_exists(false), schema(move(schema_p)), name(move(name_p)) {
|
|
150991
151007
|
}
|
|
150992
151008
|
|
|
150993
151009
|
AlterInfo::~AlterInfo() {
|
|
@@ -160794,6 +160810,8 @@ unique_ptr<ParsedExpression> Transformer::TransformLambda(duckdb_libpgquery::PGL
|
|
|
160794
160810
|
|
|
160795
160811
|
auto lhs = TransformExpression(node->lhs);
|
|
160796
160812
|
auto rhs = TransformExpression(node->rhs);
|
|
160813
|
+
D_ASSERT(lhs);
|
|
160814
|
+
D_ASSERT(rhs);
|
|
160797
160815
|
return make_unique<LambdaExpression>(move(lhs), move(rhs));
|
|
160798
160816
|
}
|
|
160799
160817
|
|
|
@@ -162398,7 +162416,9 @@ LogicalType Transformer::TransformTypeName(duckdb_libpgquery::PGTypeName *type_n
|
|
|
162398
162416
|
LogicalTypeId base_type = TransformStringToLogicalTypeId(name);
|
|
162399
162417
|
|
|
162400
162418
|
LogicalType result_type;
|
|
162401
|
-
if (base_type == LogicalTypeId::
|
|
162419
|
+
if (base_type == LogicalTypeId::LIST) {
|
|
162420
|
+
throw ParserException("LIST is not valid as a stand-alone type");
|
|
162421
|
+
} else if (base_type == LogicalTypeId::STRUCT) {
|
|
162402
162422
|
if (!type_name->typmods || type_name->typmods->length == 0) {
|
|
162403
162423
|
throw ParserException("Struct needs a name and entries");
|
|
162404
162424
|
}
|
|
@@ -162666,6 +162686,7 @@ unique_ptr<AlterStatement> Transformer::TransformAlter(duckdb_libpgquery::PGNode
|
|
|
162666
162686
|
throw NotImplementedException("ALTER TABLE option not supported yet!");
|
|
162667
162687
|
}
|
|
162668
162688
|
}
|
|
162689
|
+
result->info->if_exists = stmt->missing_ok;
|
|
162669
162690
|
|
|
162670
162691
|
return result;
|
|
162671
162692
|
}
|
|
@@ -166421,7 +166442,7 @@ BindResult ExpressionBinder::BindExpression(LambdaExpression &expr, idx_t depth,
|
|
|
166421
166442
|
if (!is_lambda) {
|
|
166422
166443
|
// this is for binding JSON
|
|
166423
166444
|
auto lhs_expr = expr.lhs->Copy();
|
|
166424
|
-
OperatorExpression arrow_expr(ExpressionType::ARROW, move(lhs_expr),
|
|
166445
|
+
OperatorExpression arrow_expr(ExpressionType::ARROW, move(lhs_expr), expr.expr->Copy());
|
|
166425
166446
|
return BindExpression(arrow_expr, depth);
|
|
166426
166447
|
}
|
|
166427
166448
|
|
|
@@ -168020,12 +168041,16 @@ unique_ptr<BoundQueryNode> Binder::BindNode(SelectNode &statement) {
|
|
|
168020
168041
|
SelectBinder select_binder(*this, context, *result, info);
|
|
168021
168042
|
vector<LogicalType> internal_sql_types;
|
|
168022
168043
|
for (idx_t i = 0; i < statement.select_list.size(); i++) {
|
|
168044
|
+
bool is_window = statement.select_list[i]->IsWindow();
|
|
168023
168045
|
LogicalType result_type;
|
|
168024
168046
|
auto expr = select_binder.Bind(statement.select_list[i], &result_type);
|
|
168025
168047
|
if (statement.aggregate_handling == AggregateHandling::FORCE_AGGREGATES && select_binder.HasBoundColumns()) {
|
|
168026
168048
|
if (select_binder.BoundAggregates()) {
|
|
168027
168049
|
throw BinderException("Cannot mix aggregates with non-aggregated columns!");
|
|
168028
168050
|
}
|
|
168051
|
+
if (is_window) {
|
|
168052
|
+
throw BinderException("Cannot group on a window clause");
|
|
168053
|
+
}
|
|
168029
168054
|
// we are forcing aggregates, and the node has columns bound
|
|
168030
168055
|
// this entry becomes a group
|
|
168031
168056
|
auto group_ref = make_unique<BoundColumnRefExpression>(
|
|
@@ -169487,33 +169512,70 @@ void Binder::BindLogicalType(ClientContext &context, LogicalType &type, const st
|
|
|
169487
169512
|
}
|
|
169488
169513
|
}
|
|
169489
169514
|
|
|
169490
|
-
static void FindMatchingPrimaryKeyColumns(vector<
|
|
169491
|
-
|
|
169492
|
-
return;
|
|
169493
|
-
}
|
|
169515
|
+
static void FindMatchingPrimaryKeyColumns(const vector<ColumnDefinition> &columns,
|
|
169516
|
+
const vector<unique_ptr<Constraint>> &constraints, ForeignKeyConstraint &fk) {
|
|
169494
169517
|
// find the matching primary key constraint
|
|
169518
|
+
bool found_constraint = false;
|
|
169519
|
+
// if no columns are defined, we will automatically try to bind to the primary key
|
|
169520
|
+
bool find_primary_key = fk.pk_columns.empty();
|
|
169495
169521
|
for (auto &constr : constraints) {
|
|
169496
169522
|
if (constr->type != ConstraintType::UNIQUE) {
|
|
169497
169523
|
continue;
|
|
169498
169524
|
}
|
|
169499
169525
|
auto &unique = (UniqueConstraint &)*constr;
|
|
169500
|
-
if (!unique.is_primary_key) {
|
|
169526
|
+
if (find_primary_key && !unique.is_primary_key) {
|
|
169501
169527
|
continue;
|
|
169502
169528
|
}
|
|
169503
|
-
|
|
169529
|
+
found_constraint = true;
|
|
169530
|
+
|
|
169531
|
+
vector<string> pk_names;
|
|
169504
169532
|
if (unique.index != DConstants::INVALID_INDEX) {
|
|
169505
|
-
|
|
169506
|
-
column_count = 1;
|
|
169533
|
+
pk_names.push_back(columns[unique.index].Name());
|
|
169507
169534
|
} else {
|
|
169508
|
-
|
|
169509
|
-
column_count = unique.columns.size();
|
|
169535
|
+
pk_names = unique.columns;
|
|
169510
169536
|
}
|
|
169511
|
-
if (
|
|
169512
|
-
|
|
169537
|
+
if (pk_names.size() != fk.fk_columns.size()) {
|
|
169538
|
+
// the number of referencing and referenced columns for foreign keys must be the same
|
|
169539
|
+
continue;
|
|
169540
|
+
}
|
|
169541
|
+
if (find_primary_key) {
|
|
169542
|
+
// found matching primary key
|
|
169543
|
+
fk.pk_columns = pk_names;
|
|
169544
|
+
return;
|
|
169513
169545
|
}
|
|
169546
|
+
if (fk.pk_columns != pk_names) {
|
|
169547
|
+
// Name mismatch
|
|
169548
|
+
continue;
|
|
169549
|
+
}
|
|
169550
|
+
// found match
|
|
169514
169551
|
return;
|
|
169515
169552
|
}
|
|
169516
|
-
|
|
169553
|
+
// no match found! examine why
|
|
169554
|
+
if (!found_constraint) {
|
|
169555
|
+
// no unique constraint or primary key
|
|
169556
|
+
string search_term = find_primary_key ? "primary key" : "primary key or unique constraint";
|
|
169557
|
+
throw BinderException("Failed to create foreign key: there is no %s for referenced table \"%s\"", search_term,
|
|
169558
|
+
fk.info.table);
|
|
169559
|
+
}
|
|
169560
|
+
// check if all the columns exist
|
|
169561
|
+
for (auto &name : fk.pk_columns) {
|
|
169562
|
+
bool found = false;
|
|
169563
|
+
for (auto &col : columns) {
|
|
169564
|
+
if (col.Name() == name) {
|
|
169565
|
+
found = true;
|
|
169566
|
+
break;
|
|
169567
|
+
}
|
|
169568
|
+
}
|
|
169569
|
+
if (!found) {
|
|
169570
|
+
throw BinderException(
|
|
169571
|
+
"Failed to create foreign key: referenced table \"%s\" does not have a column named \"%s\"",
|
|
169572
|
+
fk.info.table, name);
|
|
169573
|
+
}
|
|
169574
|
+
}
|
|
169575
|
+
auto fk_names = StringUtil::Join(fk.pk_columns, ",");
|
|
169576
|
+
throw BinderException("Failed to create foreign key: referenced table \"%s\" does not have a primary key or unique "
|
|
169577
|
+
"constraint on the columns %s",
|
|
169578
|
+
fk.info.table, fk_names);
|
|
169517
169579
|
}
|
|
169518
169580
|
|
|
169519
169581
|
void ExpressionContainsGeneratedColumn(const ParsedExpression &expr, const unordered_set<string> &gcols,
|
|
@@ -169678,13 +169740,13 @@ BoundStatement Binder::Bind(CreateStatement &stmt) {
|
|
|
169678
169740
|
D_ASSERT(fk.info.pk_keys.empty());
|
|
169679
169741
|
if (create_info.table == fk.info.table) {
|
|
169680
169742
|
fk.info.type = ForeignKeyType::FK_TYPE_SELF_REFERENCE_TABLE;
|
|
169681
|
-
FindMatchingPrimaryKeyColumns(create_info.constraints, fk);
|
|
169743
|
+
FindMatchingPrimaryKeyColumns(create_info.columns, create_info.constraints, fk);
|
|
169682
169744
|
} else {
|
|
169683
169745
|
// have to resolve referenced table
|
|
169684
169746
|
auto pk_table_entry_ptr = catalog.GetEntry<TableCatalogEntry>(context, fk.info.schema, fk.info.table);
|
|
169685
169747
|
fk_schemas.insert(pk_table_entry_ptr->schema);
|
|
169686
169748
|
D_ASSERT(fk.info.pk_keys.empty());
|
|
169687
|
-
FindMatchingPrimaryKeyColumns(pk_table_entry_ptr->constraints, fk);
|
|
169749
|
+
FindMatchingPrimaryKeyColumns(pk_table_entry_ptr->columns, pk_table_entry_ptr->constraints, fk);
|
|
169688
169750
|
for (auto &keyname : fk.pk_columns) {
|
|
169689
169751
|
auto entry = pk_table_entry_ptr->name_map.find(keyname);
|
|
169690
169752
|
if (entry == pk_table_entry_ptr->name_map.end()) {
|
|
@@ -170301,7 +170363,7 @@ BoundStatement Binder::Bind(ExecuteStatement &stmt) {
|
|
|
170301
170363
|
ConstantBinder cbinder(*constant_binder, context, "EXECUTE statement");
|
|
170302
170364
|
auto bound_expr = cbinder.Bind(stmt.values[i]);
|
|
170303
170365
|
|
|
170304
|
-
Value value = ExpressionExecutor::EvaluateScalar(*bound_expr);
|
|
170366
|
+
Value value = ExpressionExecutor::EvaluateScalar(*bound_expr, true);
|
|
170305
170367
|
bind_values.push_back(move(value));
|
|
170306
170368
|
}
|
|
170307
170369
|
unique_ptr<LogicalOperator> rebound_plan;
|
|
@@ -170967,7 +171029,8 @@ BoundStatement Binder::Bind(AlterStatement &stmt) {
|
|
|
170967
171029
|
result.names = {"Success"};
|
|
170968
171030
|
result.types = {LogicalType::BOOLEAN};
|
|
170969
171031
|
Catalog &catalog = Catalog::GetCatalog(context);
|
|
170970
|
-
auto entry = catalog.GetEntry(context, stmt.info->GetCatalogType(), stmt.info->schema, stmt.info->name,
|
|
171032
|
+
auto entry = catalog.GetEntry(context, stmt.info->GetCatalogType(), stmt.info->schema, stmt.info->name,
|
|
171033
|
+
stmt.info->if_exists);
|
|
170971
171034
|
if (entry && !entry->temporary) {
|
|
170972
171035
|
// we can only alter temporary tables/views in read-only mode
|
|
170973
171036
|
properties.read_only = false;
|
|
@@ -171428,29 +171491,58 @@ BoundStatement Binder::Bind(UpdateStatement &stmt) {
|
|
|
171428
171491
|
|
|
171429
171492
|
|
|
171430
171493
|
|
|
171494
|
+
|
|
171495
|
+
|
|
171431
171496
|
namespace duckdb {
|
|
171432
171497
|
|
|
171433
171498
|
BoundStatement Binder::Bind(VacuumStatement &stmt) {
|
|
171434
171499
|
BoundStatement result;
|
|
171435
171500
|
|
|
171501
|
+
unique_ptr<LogicalOperator> root;
|
|
171502
|
+
|
|
171436
171503
|
if (stmt.info->has_table) {
|
|
171504
|
+
D_ASSERT(!stmt.info->table);
|
|
171505
|
+
D_ASSERT(stmt.info->column_id_map.empty());
|
|
171437
171506
|
auto bound_table = Bind(*stmt.info->ref);
|
|
171438
171507
|
if (bound_table->type != TableReferenceType::BASE_TABLE) {
|
|
171439
171508
|
throw InvalidInputException("Can only vacuum/analyze base tables!");
|
|
171440
171509
|
}
|
|
171441
|
-
|
|
171510
|
+
auto ref = unique_ptr_cast<BoundTableRef, BoundBaseTableRef>(move(bound_table));
|
|
171511
|
+
stmt.info->table = ref->table;
|
|
171442
171512
|
|
|
171443
171513
|
auto &columns = stmt.info->columns;
|
|
171514
|
+
vector<unique_ptr<Expression>> select_list;
|
|
171444
171515
|
if (columns.empty()) {
|
|
171445
171516
|
// Empty means ALL columns should be vacuumed/analyzed
|
|
171446
|
-
auto &get = (LogicalGet &)*
|
|
171517
|
+
auto &get = (LogicalGet &)*ref->get;
|
|
171447
171518
|
columns.insert(columns.end(), get.names.begin(), get.names.end());
|
|
171448
171519
|
}
|
|
171520
|
+
for (auto &col_name : columns) {
|
|
171521
|
+
ColumnRefExpression colref(col_name, ref->table->name);
|
|
171522
|
+
auto result = bind_context.BindColumn(colref, 0);
|
|
171523
|
+
D_ASSERT(!result.HasError());
|
|
171524
|
+
select_list.push_back(move(result.expression));
|
|
171525
|
+
}
|
|
171526
|
+
auto table_scan = CreatePlan(*ref);
|
|
171527
|
+
D_ASSERT(table_scan->type == LogicalOperatorType::LOGICAL_GET);
|
|
171528
|
+
auto &get = (LogicalGet &)*table_scan;
|
|
171529
|
+
for (idx_t i = 0; i < get.column_ids.size(); i++) {
|
|
171530
|
+
stmt.info->column_id_map[i] = get.column_ids[i];
|
|
171531
|
+
}
|
|
171532
|
+
|
|
171533
|
+
auto projection = make_unique<LogicalProjection>(GenerateTableIndex(), move(select_list));
|
|
171534
|
+
projection->children.push_back(move(table_scan));
|
|
171535
|
+
|
|
171536
|
+
root = move(projection);
|
|
171537
|
+
}
|
|
171538
|
+
auto vacuum = make_unique<LogicalSimple>(LogicalOperatorType::LOGICAL_VACUUM, move(stmt.info));
|
|
171539
|
+
if (root) {
|
|
171540
|
+
vacuum->children.push_back(move(root));
|
|
171449
171541
|
}
|
|
171450
171542
|
|
|
171451
171543
|
result.names = {"Success"};
|
|
171452
171544
|
result.types = {LogicalType::BOOLEAN};
|
|
171453
|
-
result.plan =
|
|
171545
|
+
result.plan = move(vacuum);
|
|
171454
171546
|
properties.return_type = StatementReturnType::NOTHING;
|
|
171455
171547
|
return result;
|
|
171456
171548
|
}
|
|
@@ -174466,8 +174558,11 @@ BindResult ColumnAliasBinder::BindAlias(ExpressionBinder &enclosing_binder, Colu
|
|
|
174466
174558
|
return BindResult(StringUtil::Format("Alias %s is not found.", expr.ToString()));
|
|
174467
174559
|
}
|
|
174468
174560
|
|
|
174561
|
+
if (in_alias) {
|
|
174562
|
+
return BindResult("Cannot resolve self-referential alias");
|
|
174563
|
+
}
|
|
174564
|
+
|
|
174469
174565
|
// found an alias: bind the alias expression
|
|
174470
|
-
D_ASSERT(!in_alias);
|
|
174471
174566
|
auto expression = node.original_expressions[alias_entry->second]->Copy();
|
|
174472
174567
|
in_alias = true;
|
|
174473
174568
|
auto result = enclosing_binder.BindExpression(&expression, depth, root_expression);
|
|
@@ -176779,6 +176874,15 @@ namespace duckdb {
|
|
|
176779
176874
|
Planner::Planner(ClientContext &context) : binder(Binder::CreateBinder(context)), context(context) {
|
|
176780
176875
|
}
|
|
176781
176876
|
|
|
176877
|
+
static void CheckTreeDepth(const LogicalOperator &op, idx_t max_depth, idx_t depth = 0) {
|
|
176878
|
+
if (depth >= max_depth) {
|
|
176879
|
+
throw ParserException("Maximum tree depth of %lld exceeded in logical planner", max_depth);
|
|
176880
|
+
}
|
|
176881
|
+
for (auto &child : op.children) {
|
|
176882
|
+
CheckTreeDepth(*child, max_depth, depth + 1);
|
|
176883
|
+
}
|
|
176884
|
+
}
|
|
176885
|
+
|
|
176782
176886
|
void Planner::CreatePlan(SQLStatement &statement) {
|
|
176783
176887
|
auto &profiler = QueryProfiler::Get(context);
|
|
176784
176888
|
auto parameter_count = statement.n_param;
|
|
@@ -176797,6 +176901,8 @@ void Planner::CreatePlan(SQLStatement &statement) {
|
|
|
176797
176901
|
this->types = bound_statement.types;
|
|
176798
176902
|
this->plan = move(bound_statement.plan);
|
|
176799
176903
|
|
|
176904
|
+
auto max_tree_depth = ClientConfig::GetConfig(context).max_expression_depth;
|
|
176905
|
+
CheckTreeDepth(*plan, max_tree_depth);
|
|
176800
176906
|
} catch (ParameterNotResolvedException &ex) {
|
|
176801
176907
|
// parameter types could not be resolved
|
|
176802
176908
|
this->names = {"unknown"};
|