Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
328 changes: 326 additions & 2 deletions CMakeLists.txt

Large diffs are not rendered by default.

52 changes: 40 additions & 12 deletions src/duckdb/extension/core_functions/aggregate/algebraic/avg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,27 +239,47 @@ struct TimeTZAverageOperation : public BaseSumOperation<AverageSetOperation, Add
}
};

LogicalType GetAvgStateType(const AggregateFunction &function) {
child_list_t<LogicalType> children;
children.emplace_back("count", LogicalType::UBIGINT);
children.emplace_back("value", function.arguments[0]);
return LogicalType::STRUCT(std::move(children));
}

LogicalType GetKahanAvgStateType(const AggregateFunction &function) {
child_list_t<LogicalType> children;
children.emplace_back("count", LogicalType::UBIGINT);
children.emplace_back("value", LogicalType::DOUBLE);
children.emplace_back("err", LogicalType::DOUBLE);
return LogicalType::STRUCT(std::move(children));
}

AggregateFunction GetAverageAggregate(PhysicalType type) {
switch (type) {
case PhysicalType::INT16: {
return AggregateFunction::UnaryAggregate<AvgState<int64_t>, int16_t, double, IntegerAverageOperation>(
LogicalType::SMALLINT, LogicalType::DOUBLE);
LogicalType::SMALLINT, LogicalType::DOUBLE)
.SetStructStateExport(GetAvgStateType);
}
case PhysicalType::INT32: {
return AggregateFunction::UnaryAggregate<AvgState<hugeint_t>, int32_t, double, IntegerAverageOperationHugeint>(
LogicalType::INTEGER, LogicalType::DOUBLE);
LogicalType::INTEGER, LogicalType::DOUBLE)
.SetStructStateExport(GetAvgStateType);
}
case PhysicalType::INT64: {
return AggregateFunction::UnaryAggregate<AvgState<hugeint_t>, int64_t, double, IntegerAverageOperationHugeint>(
LogicalType::BIGINT, LogicalType::DOUBLE);
LogicalType::BIGINT, LogicalType::DOUBLE)
.SetStructStateExport(GetAvgStateType);
}
case PhysicalType::INT128: {
return AggregateFunction::UnaryAggregate<AvgState<hugeint_t>, hugeint_t, double, HugeintAverageOperation>(
LogicalType::HUGEINT, LogicalType::DOUBLE);
LogicalType::HUGEINT, LogicalType::DOUBLE)
.SetStructStateExport(GetAvgStateType);
}
case PhysicalType::INTERVAL: {
return AggregateFunction::UnaryAggregate<IntervalAvgState, interval_t, interval_t, IntervalAverageOperation>(
LogicalType::INTERVAL, LogicalType::INTERVAL);
LogicalType::INTERVAL, LogicalType::INTERVAL)
.SetStructStateExport(GetAvgStateType);
}
default:
throw InternalException("Unimplemented average aggregate");
Expand All @@ -282,6 +302,7 @@ unique_ptr<FunctionData> BindDecimalAvg(ClientContext &context, AggregateFunctio
AggregateFunctionSet AvgFun::GetFunctions() {
AggregateFunctionSet avg;

// The first is already opted-in during `BindDecimalAvg`
avg.AddFunction(AggregateFunction({LogicalTypeId::DECIMAL}, LogicalTypeId::DECIMAL, nullptr, nullptr, nullptr,
nullptr, nullptr, FunctionNullHandling::DEFAULT_NULL_HANDLING, nullptr,
BindDecimalAvg));
Expand All @@ -291,24 +312,31 @@ AggregateFunctionSet AvgFun::GetFunctions() {
avg.AddFunction(GetAverageAggregate(PhysicalType::INT128));
avg.AddFunction(GetAverageAggregate(PhysicalType::INTERVAL));
avg.AddFunction(AggregateFunction::UnaryAggregate<AvgState<double>, double, double, NumericAverageOperation>(
LogicalType::DOUBLE, LogicalType::DOUBLE));
LogicalType::DOUBLE, LogicalType::DOUBLE)
.SetStructStateExport(GetAvgStateType));

avg.AddFunction(AggregateFunction::UnaryAggregate<AvgState<hugeint_t>, int64_t, int64_t, DiscreteAverageOperation>(
LogicalType::TIMESTAMP, LogicalType::TIMESTAMP));
LogicalType::TIMESTAMP, LogicalType::TIMESTAMP)
.SetStructStateExport(GetAvgStateType));
avg.AddFunction(AggregateFunction::UnaryAggregate<AvgState<hugeint_t>, int64_t, int64_t, DiscreteAverageOperation>(
LogicalType::TIMESTAMP_TZ, LogicalType::TIMESTAMP_TZ));
LogicalType::TIMESTAMP_TZ, LogicalType::TIMESTAMP_TZ)
.SetStructStateExport(GetAvgStateType));
avg.AddFunction(AggregateFunction::UnaryAggregate<AvgState<hugeint_t>, int64_t, int64_t, DiscreteAverageOperation>(
LogicalType::TIME, LogicalType::TIME));
LogicalType::TIME, LogicalType::TIME)
.SetStructStateExport(GetAvgStateType));
avg.AddFunction(
AggregateFunction::UnaryAggregate<AvgState<hugeint_t>, dtime_tz_t, dtime_tz_t, TimeTZAverageOperation>(
LogicalType::TIME_TZ, LogicalType::TIME_TZ));
LogicalType::TIME_TZ, LogicalType::TIME_TZ)
.SetStructStateExport(GetAvgStateType));

return avg;
}

AggregateFunction FAvgFun::GetFunction() {
return AggregateFunction::UnaryAggregate<KahanAvgState, double, double, KahanAverageOperation>(LogicalType::DOUBLE,
LogicalType::DOUBLE);
auto function = AggregateFunction::UnaryAggregate<KahanAvgState, double, double, KahanAverageOperation>(
LogicalType::DOUBLE, LogicalType::DOUBLE)
.SetStructStateExport(GetKahanAvgStateType);
return function;
}

} // namespace duckdb
59 changes: 50 additions & 9 deletions src/duckdb/extension/core_functions/aggregate/distributive/sum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,37 @@ struct HugeintSumOperation : public BaseSumOperation<SumSetOperation, HugeintAdd
}
};

template <class T>
static LogicalType GetValueLogicalType();

template <>
LogicalType GetValueLogicalType<int64_t>() {
return LogicalType::BIGINT;
}
template <>
LogicalType GetValueLogicalType<hugeint_t>() {
return LogicalType::HUGEINT;
}
template <>
LogicalType GetValueLogicalType<double>() {
return LogicalType::DOUBLE;
}

template <class T>
LogicalType GetSumStateType(const AggregateFunction &function) {
child_list_t<LogicalType> child_types;
child_types.emplace_back("isset", LogicalType::BOOLEAN);

LogicalType value_type = GetValueLogicalType<T>();
// Use the return type when its physical representation matches the state type
if (function.return_type.InternalType() == value_type.InternalType()) {
value_type = function.return_type;
}
child_types.emplace_back("value", value_type);

return LogicalType::STRUCT(std::move(child_types));
}

unique_ptr<FunctionData> SumNoOverflowBind(ClientContext &context, AggregateFunction &function,
vector<unique_ptr<Expression>> &arguments) {
throw BinderException("sum_no_overflow is for internal use only!");
Expand All @@ -98,7 +129,7 @@ AggregateFunction GetSumAggregateNoOverflow(PhysicalType type) {
function.SetBindCallback(SumNoOverflowBind);
function.SetSerializeCallback(SumNoOverflowSerialize);
function.SetDeserializeCallback(SumNoOverflowDeserialize);
return function;
return function.SetStructStateExport(GetSumStateType<int64_t>);
}
case PhysicalType::INT64: {
auto function = AggregateFunction::UnaryAggregate<SumState<int64_t>, int64_t, hugeint_t, IntegerSumOperation>(
Expand All @@ -108,7 +139,7 @@ AggregateFunction GetSumAggregateNoOverflow(PhysicalType type) {
function.SetBindCallback(SumNoOverflowBind);
function.SetSerializeCallback(SumNoOverflowSerialize);
function.SetDeserializeCallback(SumNoOverflowDeserialize);
return function;
return function.SetStructStateExport(GetSumStateType<int64_t>);
}
default:
throw BinderException("Unsupported internal type for sum_no_overflow");
Expand Down Expand Up @@ -164,13 +195,13 @@ AggregateFunction GetSumAggregate(PhysicalType type) {
auto function = AggregateFunction::UnaryAggregate<SumState<int64_t>, bool, hugeint_t, IntegerSumOperation>(
LogicalType::BOOLEAN, LogicalType::HUGEINT);
function.SetOrderDependent(AggregateOrderDependent::NOT_ORDER_DEPENDENT);
return function;
return function.SetStructStateExport(GetSumStateType<int64_t>);
}
case PhysicalType::INT16: {
auto function = AggregateFunction::UnaryAggregate<SumState<int64_t>, int16_t, hugeint_t, IntegerSumOperation>(
LogicalType::SMALLINT, LogicalType::HUGEINT);
function.SetOrderDependent(AggregateOrderDependent::NOT_ORDER_DEPENDENT);
return function;
return function.SetStructStateExport(GetSumStateType<int64_t>);
}

case PhysicalType::INT32: {
Expand All @@ -179,22 +210,22 @@ AggregateFunction GetSumAggregate(PhysicalType type) {
LogicalType::INTEGER, LogicalType::HUGEINT);
function.SetStatisticsCallback(SumPropagateStats);
function.SetOrderDependent(AggregateOrderDependent::NOT_ORDER_DEPENDENT);
return function;
return function.SetStructStateExport(GetSumStateType<hugeint_t>);
}
case PhysicalType::INT64: {
auto function =
AggregateFunction::UnaryAggregate<SumState<hugeint_t>, int64_t, hugeint_t, SumToHugeintOperation>(
LogicalType::BIGINT, LogicalType::HUGEINT);
function.SetStatisticsCallback(SumPropagateStats);
function.SetOrderDependent(AggregateOrderDependent::NOT_ORDER_DEPENDENT);
return function;
return function.SetStructStateExport(GetSumStateType<hugeint_t>);
}
case PhysicalType::INT128: {
auto function =
AggregateFunction::UnaryAggregate<SumState<hugeint_t>, hugeint_t, hugeint_t, HugeintSumOperation>(
LogicalType::HUGEINT, LogicalType::HUGEINT);
function.SetOrderDependent(AggregateOrderDependent::NOT_ORDER_DEPENDENT);
return function;
return function.SetStructStateExport(GetSumStateType<hugeint_t>);
}
default:
throw InternalException("Unimplemented sum aggregate");
Expand Down Expand Up @@ -283,7 +314,8 @@ AggregateFunctionSet SumFun::GetFunctions() {
sum.AddFunction(GetSumAggregate(PhysicalType::INT64));
sum.AddFunction(GetSumAggregate(PhysicalType::INT128));
sum.AddFunction(AggregateFunction::UnaryAggregate<SumState<double>, double, double, NumericSumOperation>(
LogicalType::DOUBLE, LogicalType::DOUBLE));
LogicalType::DOUBLE, LogicalType::DOUBLE)
.SetStructStateExport(GetSumStateType<double>));
sum.AddFunction(AggregateFunction::UnaryAggregate<BignumState, bignum_t, bignum_t, BignumOperation>(
LogicalType::BIGNUM, LogicalType::BIGNUM));
return sum;
Expand All @@ -301,9 +333,18 @@ AggregateFunctionSet SumNoOverflowFun::GetFunctions() {
return sum_no_overflow;
}

LogicalType GetKahanSumStateType(const AggregateFunction &function) {
child_list_t<LogicalType> children;
children.emplace_back("isset", LogicalType::BOOLEAN);
children.emplace_back("value", LogicalType::DOUBLE);
children.emplace_back("err", LogicalType::DOUBLE);
return LogicalType::STRUCT(std::move(children));
}

AggregateFunction KahanSumFun::GetFunction() {
return AggregateFunction::UnaryAggregate<KahanSumState, double, double, KahanSumOperation>(LogicalType::DOUBLE,
LogicalType::DOUBLE);
LogicalType::DOUBLE)
.SetStructStateExport(GetKahanSumStateType);
}

} // namespace duckdb
2 changes: 2 additions & 0 deletions src/duckdb/extension/core_functions/function_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ static const StaticFunctionDefinition core_functions[] = {
DUCKDB_SCALAR_FUNCTION_SET(GenerateSeriesFun),
DUCKDB_SCALAR_FUNCTION(GetBitFun),
DUCKDB_SCALAR_FUNCTION(GetCurrentTimestampFun),
DUCKDB_SCALAR_FUNCTION(GetTypeFun),
DUCKDB_SCALAR_FUNCTION_SET_ALIAS(GradeUpFun),
DUCKDB_SCALAR_FUNCTION_SET(GreatestFun),
DUCKDB_SCALAR_FUNCTION_SET(GreatestCommonDivisorFun),
Expand Down Expand Up @@ -266,6 +267,7 @@ static const StaticFunctionDefinition core_functions[] = {
DUCKDB_SCALAR_FUNCTION_SET(MakeTimestampFun),
DUCKDB_SCALAR_FUNCTION_SET(MakeTimestampMsFun),
DUCKDB_SCALAR_FUNCTION_SET(MakeTimestampNsFun),
DUCKDB_SCALAR_FUNCTION(MakeTypeFun),
DUCKDB_SCALAR_FUNCTION_SET(MapFun),
DUCKDB_SCALAR_FUNCTION(MapConcatFun),
DUCKDB_SCALAR_FUNCTION(MapEntriesFun),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,26 @@ struct TypeOfFun {
static ScalarFunction GetFunction();
};

struct GetTypeFun {
static constexpr const char *Name = "get_type";
static constexpr const char *Parameters = "expression";
static constexpr const char *Description = "Returns the type of the result of the expression";
static constexpr const char *Example = "get_type('abc')";
static constexpr const char *Categories = "";

static ScalarFunction GetFunction();
};

struct MakeTypeFun {
static constexpr const char *Name = "make_type";
static constexpr const char *Parameters = "name,...";
static constexpr const char *Description = "Construct a type from its name and optional parameters";
static constexpr const char *Example = "make_type('DECIMAL', 10, 2)";
static constexpr const char *Categories = "";

static ScalarFunction GetFunction();
};

struct CanCastImplicitlyFun {
static constexpr const char *Name = "can_cast_implicitly";
static constexpr const char *Parameters = "source_type,target_type";
Expand Down
16 changes: 10 additions & 6 deletions src/duckdb/extension/core_functions/lambda_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "duckdb/planner/expression/bound_function_expression.hpp"
#include "duckdb/planner/expression/bound_cast_expression.hpp"
#include "duckdb/planner/expression/bound_lambda_expression.hpp"

namespace duckdb {

Expand All @@ -22,10 +23,11 @@ struct LambdaExecuteInfo {

// get the input types for the input chunk
vector<LogicalType> input_types;

input_types.push_back(child_vector.GetType());
if (has_index) {
input_types.push_back(LogicalType::BIGINT);
}
input_types.push_back(child_vector.GetType());
for (idx_t i = 1; i < args.ColumnCount(); i++) {
input_types.push_back(args.data[i].GetType());
}
Expand Down Expand Up @@ -152,8 +154,9 @@ struct ListFilterFunctor {

// slice the input chunk's corresponding vector to get the new lists
// and append them to the result
idx_t source_list_idx = execute_info.has_index ? 1 : 0;
Vector result_lists(execute_info.input_chunk.data[source_list_idx], sel, count);

// The first vector in the input chunk is always the list vector
Vector result_lists(execute_info.input_chunk.data[0], sel, count);
ListVector::Append(result, result_lists, count, 0);
}
};
Expand Down Expand Up @@ -190,8 +193,8 @@ static void ExecuteExpression(const idx_t elem_cnt, const LambdaFunctions::Colum

// reference the child vector (and the index vector)
if (info.has_index) {
info.input_chunk.data[0].Reference(index_vector);
info.input_chunk.data[1].Reference(slice);
info.input_chunk.data[0].Reference(slice);
info.input_chunk.data[1].Reference(index_vector);
} else {
info.input_chunk.data[0].Reference(slice);
}
Expand Down Expand Up @@ -247,7 +250,8 @@ LogicalType LambdaFunctions::DetermineListChildType(const LogicalType &child_typ
} else if (child_type.id() == LogicalTypeId::LIST) {
return ListType::GetChildType(child_type);
}
throw InternalException("The first argument must be a list or array type");

throw BinderException("Invalid LIST argument during lambda function binding!");
}

return child_type;
Expand Down
6 changes: 1 addition & 5 deletions src/duckdb/extension/core_functions/scalar/bit/bitstring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,8 @@ static void BitStringFunction(DataChunk &args, ExpressionState &state, Vector &r
if (idx_t(n) < input_length) {
throw InvalidInputException("Length must be equal or larger than input string");
}
idx_t len;
if (FROM_STRING) {
Bit::TryGetBitStringSize(input, len, nullptr); // string verification
}

len = Bit::ComputeBitstringLen(UnsafeNumericCast<idx_t>(n));
idx_t len = Bit::ComputeBitstringLen(UnsafeNumericCast<idx_t>(n));
string_t target = StringVector::EmptyString(result, len);
if (FROM_STRING) {
Bit::BitString(input, UnsafeNumericCast<idx_t>(n), target);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,8 @@ unique_ptr<BaseStatistics> DateTruncStatistics(vector<BaseStatistics> &child_sta
auto result = NumericStats::CreateEmpty(min_value.type());
NumericStats::SetMin(result, min_value);
NumericStats::SetMax(result, max_value);
result.CopyValidity(child_stats[0]);

result.CombineValidity(child_stats[0], child_stats[1]);
return result.ToUnique();
}

Expand Down
16 changes: 6 additions & 10 deletions src/duckdb/extension/core_functions/scalar/generic/stats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ namespace duckdb {

namespace {
struct StatsBindData : public FunctionData {
explicit StatsBindData(string stats_p = string()) : stats(std::move(stats_p)) {
explicit StatsBindData(Value stats_p = Value(LogicalType::VARIANT())) : stats(std::move(stats_p)) {
}

string stats;
Value stats;

public:
unique_ptr<FunctionData> Copy() const override {
Expand All @@ -17,18 +17,14 @@ struct StatsBindData : public FunctionData {

bool Equals(const FunctionData &other_p) const override {
auto &other = other_p.Cast<StatsBindData>();
return stats == other.stats;
return Value::NotDistinctFrom(stats, other.stats);
}
};

void StatsFunction(DataChunk &args, ExpressionState &state, Vector &result) {
auto &func_expr = state.expr.Cast<BoundFunctionExpression>();
auto &info = func_expr.bind_info->Cast<StatsBindData>();
if (info.stats.empty()) {
info.stats = "No statistics";
}
Value v(info.stats);
result.Reference(v);
result.Reference(info.stats);
}

unique_ptr<FunctionData> StatsBind(ClientContext &context, ScalarFunction &bound_function,
Expand All @@ -40,14 +36,14 @@ unique_ptr<BaseStatistics> StatsPropagateStats(ClientContext &context, FunctionS
auto &child_stats = input.child_stats;
auto &bind_data = input.bind_data;
auto &info = bind_data->Cast<StatsBindData>();
info.stats = child_stats[0].ToString();
info.stats = child_stats[0].ToStruct().CastAs(context, LogicalType::VARIANT());
return nullptr;
}

} // namespace

ScalarFunction StatsFun::GetFunction() {
ScalarFunction stats({LogicalType::ANY}, LogicalType::VARCHAR, StatsFunction, StatsBind, nullptr,
ScalarFunction stats({LogicalType::ANY}, LogicalType::VARIANT(), StatsFunction, StatsBind, nullptr,
StatsPropagateStats);
stats.SetNullHandling(FunctionNullHandling::SPECIAL_HANDLING);
stats.SetStability(FunctionStability::VOLATILE);
Expand Down
Loading
Loading