diff --git a/src/common/backend/catalog/builtin_funcs.ini b/src/common/backend/catalog/builtin_funcs.ini index 195292628..9c08bff46 100755 --- a/src/common/backend/catalog/builtin_funcs.ini +++ b/src/common/backend/catalog/builtin_funcs.ini @@ -5697,6 +5697,10 @@ "int8_avg_accum", 1, AddBuiltinFunc(_0(2746), _1("int8_avg_accum"), _2(2), _3(true), _4(false), _5(int8_avg_accum), _6(1231), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 1231, 20), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("int8_avg_accum"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "int8_avg_accum_numeric", 1, + AddBuiltinFunc(_0(5439), _1("int8_avg_accum_numeric"), _2(2), _3(false), _4(false), _5(int8_avg_accum), _6(2281), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 2281, 20), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("int8_avg_accum"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), AddFuncGroup( "int8_avg_collect", 1, AddBuiltinFunc(_0(2965), _1("int8_avg_collect"), _2(2), _3(true), _4(false), _5(int8_avg_collect), _6(1016), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 1016, 1016), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("int8_avg_collect"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) @@ -7251,6 +7255,10 @@ "numeric_accum", 1, AddBuiltinFunc(_0(1833), _1("numeric_accum"), _2(2), _3(true), _4(false), _5(numeric_accum), _6(1231), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 1231, 1700), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_accum"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("aggregate transition function"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "numeric_accum_numeric", 1, + AddBuiltinFunc(_0(5440), _1("numeric_accum_numeric"), _2(2), _3(false), _4(false), _5(numeric_accum), _6(2281), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 2281, 1700), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_accum"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("aggregate transition function"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), AddFuncGroup( "numeric_add", 1, AddBuiltinFunc(_0(1724), _1("numeric_add"), _2(2), _3(true), _4(false), _5(numeric_add), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 1700, 1700), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_add"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) @@ -7259,10 +7267,18 @@ "numeric_avg", 1, AddBuiltinFunc(_0(1837), _1("numeric_avg"), _2(1), _3(true), _4(false), _5(numeric_avg), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 1231), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_avg"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("aggregate final function"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "numeric_avg_numeric", 1, + AddBuiltinFunc(_0(5441), _1("numeric_avg_numeric"), _2(1), _3(false), _4(false), _5(numeric_avg), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_avg"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("aggregate final function"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), AddFuncGroup( "numeric_avg_accum", 1, AddBuiltinFunc(_0(2858), _1("numeric_avg_accum"), _2(2), _3(true), _4(false), _5(numeric_avg_accum), _6(1231), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 1231, 1700), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_avg_accum"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("aggregate transition function"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "numeric_avg_accum_numeric", 1, + AddBuiltinFunc(_0(5442), _1("numeric_avg_accum_numeric"), _2(2), _3(false), _4(false), _5(numeric_avg_accum), _6(1231), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 2281, 1700), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_avg_accum"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("aggregate transition function"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), AddFuncGroup( "numeric_avg_collect", 1, AddBuiltinFunc(_0(2964), _1("numeric_avg_collect"), _2(2), _3(true), _4(false), _5(numeric_avg_collect), _6(1231), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 1231, 1231), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_avg_collect"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) @@ -7395,14 +7411,26 @@ "numeric_stddev_pop", 1, AddBuiltinFunc(_0(2596), _1("numeric_stddev_pop"), _2(1), _3(true), _4(false), _5(numeric_stddev_pop), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 1231), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_stddev_pop"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("aggregate final function"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "numeric_stddev_pop_numeric", 1, + AddBuiltinFunc(_0(5443), _1("numeric_stddev_pop_numeric"), _2(1), _3(false), _4(false), _5(numeric_stddev_pop), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_stddev_pop"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("aggregate final function"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), AddFuncGroup( "numeric_stddev_samp", 1, AddBuiltinFunc(_0(1839), _1("numeric_stddev_samp"), _2(1), _3(true), _4(false), _5(numeric_stddev_samp), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 1231), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_stddev_samp"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("aggregate final function"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "numeric_stddev_samp_numeric", 1, + AddBuiltinFunc(_0(5444), _1("numeric_stddev_samp_numeric"), _2(1), _3(false), _4(false), _5(numeric_stddev_samp), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_stddev_samp"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("aggregate final function"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), AddFuncGroup( "numeric_sub", 1, AddBuiltinFunc(_0(1725), _1("numeric_sub"), _2(2), _3(true), _4(false), _5(numeric_sub), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 1700, 1700), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_sub"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "numeric_sum", 1, + AddBuiltinFunc(_0(5435), _1("numeric_sum"), _2(1), _3(false), _4(false), _5(numeric_sum), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_sum"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), AddFuncGroup( "numeric_text", 1, AddBuiltinFunc(_0(4171), _1("numeric_text"), _2(1), _3(true), _4(false), _5(numeric_text), _6(25), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 1700), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_text"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) @@ -7423,10 +7451,18 @@ "numeric_var_pop", 1, AddBuiltinFunc(_0(2514), _1("numeric_var_pop"), _2(1), _3(true), _4(false), _5(numeric_var_pop), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 1231), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_var_pop"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("aggregate final function"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "numeric_var_pop_numeric", 1, + AddBuiltinFunc(_0(5445), _1("numeric_var_pop_numeric"), _2(1), _3(false), _4(false), _5(numeric_var_pop), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_var_pop"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("aggregate final function"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), AddFuncGroup( "numeric_var_samp", 1, AddBuiltinFunc(_0(1838), _1("numeric_var_samp"), _2(1), _3(true), _4(false), _5(numeric_var_samp), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 1231), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_var_samp"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("aggregate final function"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "numeric_var_samp_numeric", 1, + AddBuiltinFunc(_0(5446), _1("numeric_var_samp_numeric"), _2(1), _3(false), _4(false), _5(numeric_var_samp), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2281), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_var_samp"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("aggregate final function"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), AddFuncGroup( "numeric_varchar", 1, AddBuiltinFunc(_0(4183), _1("numeric_varchar"), _2(1), _3(true), _4(false), _5(numeric_varchar), _6(1043), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 1700), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_varchar"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) diff --git a/src/common/backend/utils/adt/numeric.cpp b/src/common/backend/utils/adt/numeric.cpp index 1b12cf975..5bbd025e8 100644 --- a/src/common/backend/utils/adt/numeric.cpp +++ b/src/common/backend/utils/adt/numeric.cpp @@ -68,6 +68,27 @@ typedef struct { hyperLogLogState abbr_card; /* cardinality estimator */ } NumericSortSupport; +typedef struct NumericSumAccum +{ + int ndigits; + int weight; + int dscale; + int num_uncarried; + bool have_carry_space; + int32 *pos_digits; + int32 *neg_digits; +} NumericSumAccum; + +typedef struct NumericAggState +{ + bool calcSumX2; /* if true, calculate sumX2 */ + bool isNaN; /* true if any processed number was NaN */ + MemoryContext agg_context; /* context we're calculating in */ + int64 N; /* count of processed numbers */ + NumericSumAccum sumX; /* sum of processed numbers */ + NumericSumAccum sumX2; /* sum of squares of processed numbers */ +} NumericAggState; + #define NUMERIC_ABBREV_BITS (SIZEOF_DATUM * BITS_PER_BYTE) #if SIZEOF_DATUM == 8 #define DatumGetNumericAbbrev(d) ((int64)d) @@ -207,6 +228,11 @@ static void compute_bucket( Numeric operand, Numeric bound1, Numeric bound2, NumericVar* count_var, NumericVar* result_var); static void remove_tail_zero(char *ascii); +static void accum_sum_add(NumericSumAccum *accum, NumericVar *var1); +static void accum_sum_rescale(NumericSumAccum *accum, NumericVar *val); +static void accum_sum_carry(NumericSumAccum *accum); +static void accum_sum_final(NumericSumAccum *accum, NumericVar *result); + /* * @Description: call corresponding big integer operator functions. * @@ -3325,6 +3351,27 @@ Datum numeric_float4(PG_FUNCTION_ARGS) * ---------------------------------------------------------------------- */ +static NumericAggState *makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2) +{ + NumericAggState *state; + MemoryContext agg_context; + MemoryContext old_context; + + if (!AggCheckCallContext(fcinfo, &agg_context)) { + elog(ERROR, "aggregate function called in non-aggregate context"); + } + + old_context = MemoryContextSwitchTo(agg_context); + + state = (NumericAggState *) palloc0(sizeof(NumericAggState)); + state->calcSumX2 = calcSumX2; + state->agg_context = agg_context; + + MemoryContextSwitchTo(old_context); + + return state; +} + static ArrayType* do_numeric_accum(ArrayType* transarray, Numeric newval) { Datum* transdatums = NULL; @@ -3354,6 +3401,45 @@ static ArrayType* do_numeric_accum(ArrayType* transarray, Numeric newval) return result; } +static void do_numeric_accum_numeric(NumericAggState *state, Numeric newval) +{ + NumericVar X; + NumericVar X2; + MemoryContext old_context; + uint16 num1Flags = NUMERIC_NB_FLAGBITS(newval); + /* result is NaN if any processed number is NaN */ + if (state->isNaN || NUMERIC_FLAG_IS_NAN(num1Flags)) { + state->isNaN = true; + return; + } + + if (NUMERIC_FLAG_IS_BI(num1Flags)) { + // num1 is int64/128, num2 is numeric, turn num1 to numeric + newval = makeNumericNormal(newval); + } + + /* load processed number in short-lived context */ + init_var_from_num(newval, &X); + + /* if we need X^2, calculate that in short-lived context */ + if (state->calcSumX2) { + init_var(&X2); + mul_var(&X, &X, &X2, X.dscale * 2); + } + + /* The rest of this needs to work in the aggregate context */ + old_context = MemoryContextSwitchTo(state->agg_context); + + state->N++; + + /* Accumulate sums */ + accum_sum_add(&(state->sumX), &X); + + if (state->calcSumX2) + accum_sum_add(&(state->sumX2), &X2); + MemoryContextSwitchTo(old_context); +} + /* * Improve avg performance by not caclulating sum(X*X). */ @@ -3390,6 +3476,23 @@ Datum numeric_accum(PG_FUNCTION_ARGS) PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval)); } +Datum numeric_accum_numeric(PG_FUNCTION_ARGS) +{ + NumericAggState *state; + + state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); + + if (!PG_ARGISNULL(1)) { + /* Create the state data when we see the first non-null input. */ + if (state == NULL) + state = makeNumericAggState(fcinfo, true); + + do_numeric_accum_numeric(state, PG_GETARG_NUMERIC(1)); + } + + PG_RETURN_POINTER(state); +} + /* * Optimized case for average of numeric. */ @@ -3401,6 +3504,23 @@ Datum numeric_avg_accum(PG_FUNCTION_ARGS) PG_RETURN_ARRAYTYPE_P(do_numeric_avg_accum(transarray, newval)); } +Datum numeric_avg_accum_numeric(PG_FUNCTION_ARGS) +{ + NumericAggState *state; + state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); + + if (!PG_ARGISNULL(1)) { + /* Create the state data when we see the first non-null input. */ + if (state == NULL) { + state = makeNumericAggState(fcinfo, false); + } + + do_numeric_accum_numeric(state, PG_GETARG_NUMERIC(1)); + } + + PG_RETURN_POINTER(state); +} + /* * Integer data types all use Numeric accumulators to share code and * avoid risk of overflow. For int2 and int4 inputs, Numeric accumulation @@ -3457,6 +3577,28 @@ Datum int8_avg_accum(PG_FUNCTION_ARGS) PG_RETURN_ARRAYTYPE_P(do_numeric_avg_accum(transarray, newval)); } +Datum int8_avg_accum_numeric(PG_FUNCTION_ARGS) +{ + NumericAggState *state; + + state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); + + if (!PG_ARGISNULL(1)) { + Numeric newval; + + newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, + PG_GETARG_DATUM(1))); + /* Create the state data when we see the first non-null input. */ + if (state == NULL) { + state = makeNumericAggState(fcinfo, true); + } + do_numeric_accum_numeric(state, newval); + } + + PG_RETURN_POINTER(state); + +} + Datum numeric_avg(PG_FUNCTION_ARGS) { ArrayType* transarray = PG_GETARG_ARRAYTYPE_P(0); @@ -3479,6 +3621,86 @@ Datum numeric_avg(PG_FUNCTION_ARGS) PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, NumericGetDatum(sumX), NumericGetDatum(N))); } +Datum numeric_avg_numeric(PG_FUNCTION_ARGS) +{ + NumericAggState *state; + Datum N_datum; + Datum sumX_datum; + NumericVar sumX_var; + state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); + if (state == NULL) { + PG_RETURN_NULL(); + } + if (state->isNaN) { + PG_RETURN_NUMERIC(make_result(&const_nan)); + } + + N_datum = DirectFunctionCall1(int8_numeric, Int64GetDatum(state->N)); + init_var(&sumX_var); + accum_sum_final(&state->sumX, &sumX_var); + sumX_datum = NumericGetDatum(make_result(&sumX_var)); + free_var(&sumX_var); + PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum)); +} + +Datum numeric_sum(PG_FUNCTION_ARGS) +{ + NumericAggState *state; + NumericVar sumX_var; + Numeric result; + + state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); + if (state == NULL) { + PG_RETURN_NULL(); + } + + if (state->isNaN) { + PG_RETURN_NUMERIC(make_result(&const_nan)); + } + + init_var(&sumX_var); + accum_sum_final(&state->sumX, &sumX_var); + result = make_result(&sumX_var); + free_var(&sumX_var); + + PG_RETURN_NUMERIC(result); +} + +static void int8_to_numericvar(int64 val, NumericVar *var) +{ + uint64 uval, newuval; + NumericDigit *ptr; + int ndigits; + + /* int8 can require at most 19 decimal digits; add one for safety */ + alloc_var(var, 20 / DEC_DIGITS); + if (val < 0) { + var->sign = NUMERIC_NEG; + uval = -val; + } else { + var->sign = NUMERIC_POS; + uval = val; + } + var->dscale = 0; + if (val == 0) { + var->ndigits = 0; + var->weight = 0; + return; + } + ptr = var->digits + var->ndigits; + ndigits = 0; + do { + ptr--; + ndigits++; + newuval = uval / NBASE; + *ptr = uval - newuval * NBASE; + uval = newuval; + } while (uval); + var->digits = ptr; + var->ndigits = ndigits; + var->weight = ndigits - 1; +} + /* * Workhorse routine for the standard deviance and variance * aggregates. 'transarray' is the aggregate's transition @@ -3578,6 +3800,86 @@ static Numeric numeric_stddev_internal(ArrayType* transarray, bool variance, boo return res; } +static Numeric numeric_stddev_internal_numeric(NumericAggState* state, bool variance, bool sample, bool* is_null) +{ + Numeric res; + NumericVar vN, vsumX, vsumX2, vNminus1; + NumericVar* comp = NULL; + int rscale; + + /* Deal with empty input and NaN-input cases */ + if (state == NULL) { + *is_null = true; + return NULL; + } + + *is_null = false; + + if (state->isNaN) { + return make_result(&const_nan); + } + + init_var(&vN); + init_var(&vsumX); + init_var(&vsumX2); + + int8_to_numericvar(state->N, &vN); + /* + * Sample stddev and variance are undefined when N <= 1; population stddev + * is undefined when N == 0. Return NULL in either case. + */ + if (sample) { + comp = &const_one; + } else { + comp = &const_zero; + } + + if (cmp_var(&vN, comp) <= 0) { + *is_null = true; + return NULL; + } + + init_var(&vNminus1); + sub_var(&vN, &const_one, &vNminus1); + + /* + * Handle Big Integer + */ + accum_sum_final(&(state->sumX), &vsumX); + accum_sum_final(&(state->sumX2), &vsumX2); + + /* compute rscale for mul_var calls */ + rscale = vsumX.dscale * 2; + + mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */ + mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */ + sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */ + + if (cmp_var(&vsumX2, &const_zero) <= 0) { + /* Watch out for roundoff error producing a negative numerator */ + res = make_result(&const_zero); + } else { + if (sample) { + mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */ + } else { + mul_var(&vN, &vN, &vNminus1, 0); /* N * N */ + } + rscale = select_div_scale(&vsumX2, &vNminus1); + div_var(&vsumX2, &vNminus1, &vsumX, rscale, true); /* variance */ + if (!variance) { + sqrt_var(&vsumX, &vsumX, rscale); /* stddev */ + } + + res = make_result(&vsumX); + } + + free_var(&vNminus1); + free_var(&vsumX); + free_var(&vsumX2); + + return res; +} + Datum numeric_var_samp(PG_FUNCTION_ARGS) { Numeric res; @@ -3591,6 +3893,23 @@ Datum numeric_var_samp(PG_FUNCTION_ARGS) PG_RETURN_NUMERIC(res); } +Datum numeric_var_samp_numeric(PG_FUNCTION_ARGS) +{ + NumericAggState *state; + Numeric res; + bool is_null = false; + + state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); + + res = numeric_stddev_internal_numeric(state, true, true, &is_null); + + if (is_null) { + PG_RETURN_NULL(); + } else { + PG_RETURN_NUMERIC(res); + } +} + Datum numeric_stddev_samp(PG_FUNCTION_ARGS) { Numeric res; @@ -3604,6 +3923,38 @@ Datum numeric_stddev_samp(PG_FUNCTION_ARGS) PG_RETURN_NUMERIC(res); } +void stddev_create_state_4_vector(PG_FUNCTION_ARGS) +{ + NumericAggState *state = makeNumericAggState(fcinfo, true); + state->N = DatumGetInt64(DirectFunctionCall1(numeric_int8, PG_GETARG_DATUM(1))); + NumericVar* sumX = (NumericVar*)palloc0(sizeof(NumericVar)); + NumericVar* sumX2 = (NumericVar*)palloc0(sizeof(NumericVar)); + init_var_from_num(DatumGetNumeric(PG_GETARG_DATUM(2)), sumX); + init_var_from_num(DatumGetNumeric(PG_GETARG_DATUM(3)), sumX2); + accum_sum_add(&(state->sumX), sumX); + accum_sum_add(&(state->sumX2), sumX2); + + fcinfo->arg[0] = PointerGetDatum(state); + return ; +} + +Datum numeric_stddev_samp_numeric(PG_FUNCTION_ARGS) +{ + NumericAggState *state; + Numeric res; + bool is_null = false; + + state = (fcinfo->isnull && PG_ARGISNULL(0)) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); + + res = numeric_stddev_internal_numeric(state, false, true, &is_null); + + if (is_null) { + PG_RETURN_NULL(); + } else { + PG_RETURN_NUMERIC(res); + } +} + Datum numeric_var_pop(PG_FUNCTION_ARGS) { Numeric res; @@ -3617,6 +3968,23 @@ Datum numeric_var_pop(PG_FUNCTION_ARGS) PG_RETURN_NUMERIC(res); } +Datum numeric_var_pop_numeric(PG_FUNCTION_ARGS) +{ + NumericAggState *state; + Numeric res; + bool is_null = false; + + state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); + + res = numeric_stddev_internal_numeric(state, true, false, &is_null); + + if (is_null) { + PG_RETURN_NULL(); + } else { + PG_RETURN_NUMERIC(res); + } +} + Datum numeric_stddev_pop(PG_FUNCTION_ARGS) { Numeric res; @@ -3630,6 +3998,23 @@ Datum numeric_stddev_pop(PG_FUNCTION_ARGS) PG_RETURN_NUMERIC(res); } +Datum numeric_stddev_pop_numeric(PG_FUNCTION_ARGS) +{ + NumericAggState *state; + Numeric res; + bool is_null = false; + + state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); + + res = numeric_stddev_internal_numeric(state, false, false, &is_null); + + if (is_null) { + PG_RETURN_NULL(); + } else { + PG_RETURN_NUMERIC(res); + } +} + /* * SUM transition functions for integer datatypes. * @@ -19628,3 +20013,277 @@ Datum bool_numeric(PG_FUNCTION_ARGS) PG_RETURN_NUMERIC(res); } + +static void accum_sum_add(NumericSumAccum *accum, NumericVar *val) +{ + int32 *accum_digits; + int i, val_i; + int val_ndigits; + NumericDigit *val_digits; + + /* + * If we have accumulated too many values since the last carry + * propagation, do it now, to avoid overflowing. (We could allow more + * than NBASE - 1, if we reserved two extra digits, rather than one, for + * carry propagation. But even with NBASE - 1, this needs to be done so + * seldom, that the performance difference is negligible.) + */ + if (accum->num_uncarried == NBASE - 1) { + accum_sum_carry(accum); + } + + /* + * Adjust the weight or scale of the old value, so that it can accommodate + * the new value. + */ + accum_sum_rescale(accum, val); + + /* */ + if (val->sign == NUMERIC_POS) { + accum_digits = accum->pos_digits; + } else { + accum_digits = accum->neg_digits; + } + /* copy these values into local vars for speed in loop */ + val_ndigits = val->ndigits; + val_digits = val->digits; + + i = accum->weight - val->weight; + for (val_i = 0; val_i < val_ndigits; val_i++) { + accum_digits[i] += (int32) val_digits[val_i]; + i++; + } + + accum->num_uncarried++; +} + +static void accum_sum_carry(NumericSumAccum *accum) +{ + int i; + int ndigits; + int32 *dig; + int32 carry; + int32 newdig = 0; + + if (accum->num_uncarried == 0) { + return; + } + + Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0); + + ndigits = accum->ndigits; + + dig = accum->pos_digits; + carry = 0; + for (i = ndigits - 1; i >= 0; i--) { + newdig = dig[i] + carry; + if (newdig >= NBASE) { + carry = newdig / NBASE; + newdig -= carry * NBASE; + } else { + carry = 0; + } + dig[i] = newdig; + } + + if (newdig > 0) { + accum->have_carry_space = false; + } + + dig = accum->neg_digits; + carry = 0; + for (i = ndigits - 1; i >= 0; i--) { + newdig = dig[i] + carry; + if (newdig >= NBASE) { + carry = newdig / NBASE; + newdig -= carry * NBASE; + } else { + carry = 0; + } + dig[i] = newdig; + } + if (newdig > 0) { + accum->have_carry_space = false; + } + + accum->num_uncarried = 0; +} + +static void accum_sum_rescale(NumericSumAccum *accum, NumericVar *val) +{ + int old_weight = accum->weight; + int old_ndigits = accum->ndigits; + int accum_ndigits; + int accum_weight; + int accum_rscale; + int val_rscale; + + accum_weight = old_weight; + accum_ndigits = old_ndigits; + + if (val->weight >= accum_weight) { + accum_weight = val->weight + 1; + accum_ndigits = accum_ndigits + (accum_weight - old_weight); + } else if (!accum->have_carry_space) { + accum_weight++; + accum_ndigits++; + } + + /* Is the new value wider on the right side? */ + accum_rscale = accum_ndigits - accum_weight - 1; + val_rscale = val->ndigits - val->weight - 1; + if (val_rscale > accum_rscale) { + accum_ndigits = accum_ndigits + (val_rscale - accum_rscale); + } + + if (accum_ndigits != old_ndigits || + accum_weight != old_weight) { + int32 *new_pos_digits; + int32 *new_neg_digits; + int weightdiff; + size_t size = (size_t)accum_ndigits * sizeof(int32); + + weightdiff = accum_weight - old_weight; + + new_pos_digits = (int32*)palloc0(size); + new_neg_digits = (int32*)palloc0(size); + + if (accum->pos_digits) { + errno_t rc = memcpy_s(&new_pos_digits[weightdiff], size, accum->pos_digits, + (size_t)old_ndigits * sizeof(int32)); + securec_check(rc, "\0", "\0"); + pfree(accum->pos_digits); + + rc = memcpy_s(&new_neg_digits[weightdiff], size, accum->neg_digits, + old_ndigits * sizeof(int32)); + securec_check(rc, "\0", "\0"); + pfree(accum->neg_digits); + } + + accum->pos_digits = new_pos_digits; + accum->neg_digits = new_neg_digits; + + accum->weight = accum_weight; + accum->ndigits = accum_ndigits; + + Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0); + accum->have_carry_space = true; + } + + if (val->dscale > accum->dscale) + accum->dscale = val->dscale; +} + +static void accum_sum_final(NumericSumAccum *accum, NumericVar *result) +{ + int i; + NumericVar pos_var; + NumericVar neg_var; + + if (accum->ndigits == 0) { + set_var_from_var(&const_zero, result); + return; + } + + /* Perform final carry */ + accum_sum_carry(accum); + + /* Create NumericVars representing the positive and negative sums */ + init_var(&pos_var); + init_var(&neg_var); + + pos_var.ndigits = neg_var.ndigits = accum->ndigits; + pos_var.weight = neg_var.weight = accum->weight; + pos_var.dscale = neg_var.dscale = accum->dscale; + pos_var.sign = NUMERIC_POS; + neg_var.sign = NUMERIC_NEG; + + pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits); + neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits); + + for (i = 0; i < accum->ndigits; i++) { + Assert(accum->pos_digits[i] < NBASE); + pos_var.digits[i] = (int16) accum->pos_digits[i]; + + Assert(accum->neg_digits[i] < NBASE); + neg_var.digits[i] = (int16) accum->neg_digits[i]; + } + + /* And add them together */ + add_var(&pos_var, &neg_var, result); + + /* Remove leading/trailing zeroes */ + strip_var(result); +} + +bool numeric_agg_trans_initvalisnull(Oid transfn_oid, bool initvalisnull) +{ + if (transfn_oid == 5440 || transfn_oid == 5442 || transfn_oid == 5439) { + return true; + } + + return initvalisnull; +} + +void numeric_transfn_info_change(Oid aggfn_oid, Oid *transfn_oid, Oid *transtype) +{ + Oid old_type = *transtype; + *transtype = 2281; + + switch (aggfn_oid) { + case 2100: + case 2107: + *transfn_oid = 5439; + break; + case 2103: + case 2114: + *transfn_oid = 5442; + break; + case 2723: + case 2646: + case 2153: + case 2729: + case 2717: + case 2159: + *transfn_oid = 5440; + break; + default: + *transtype = old_type; + } +} + +void numeric_finalfn_info_change(Oid aggfn_oid, Oid *finalfn_oid) +{ + switch (aggfn_oid) { + case 2100: + case 2103: + *finalfn_oid = 5441; + break; + case 2107: + case 2114: + *finalfn_oid = 5435; + break; + case 2723: + *finalfn_oid = 5445; + break; + case 2646: + case 2153: + *finalfn_oid = 5446; + break; + case 2729: + *finalfn_oid = 5443; + break; + case 2717: + case 2159: + *finalfn_oid = 5444; + break; + default: + return; + } +} + +void numeric_aggfn_info_change(Oid aggfn_oid, Oid *transfn_oid, Oid *transtype, Oid *finalfn_oid) +{ + numeric_transfn_info_change(aggfn_oid, transfn_oid, transtype); + numeric_finalfn_info_change(aggfn_oid, finalfn_oid); +} \ No newline at end of file diff --git a/src/gausskernel/optimizer/util/clauses.cpp b/src/gausskernel/optimizer/util/clauses.cpp index af9a836a0..de58f7c26 100644 --- a/src/gausskernel/optimizer/util/clauses.cpp +++ b/src/gausskernel/optimizer/util/clauses.cpp @@ -691,6 +691,35 @@ static void count_agg_clauses_walker_isa(Node* node, count_agg_clauses_context* costs->transitionSpace += avgwidth + 2 * sizeof(void*); costs->aggWidth += avgwidth; } else if (aggtranstype == INTERNALOID) { +#ifndef ENABLE_MULTIPLE_NODES + /* + * XXX: we apply the pg commit 69c8fbac201652282e18b0e2e301d4ada991fbde + * but the difference of pg_aggregate bwtween pg and og + * we have to do some hard code here(og's pg_aggregate doesn't have the column aggtransspace) + */ + switch (aggtransfn) { + case 5439: /* int8_avg_accum_numeric */ + costs->transitionSpace +=48; + costs->aggWidth += 48; + break; + case 5440: /* numeric_accum_numeric */ + case 5442: /* numeric_avg_accum_numeric */ + costs->transitionSpace += 128; + costs->aggWidth += 128; + break; + default: + /* + * INTERNAL transition type is a special case: although INTERNAL + * is pass-by-value, it's almost certainly being used as a pointer + * to some large data structure. We assume usage of + * ALLOCSET_DEFAULT_INITSIZE, which is a good guess if the data is + * being kept in a private memory context, as is done by + * array_agg() for instance. + */ + costs->transitionSpace += ALLOCSET_DEFAULT_INITSIZE; + costs->aggWidth += ALLOCSET_DEFAULT_INITSIZE; + } +#else /* * INTERNAL transition type is a special case: although INTERNAL * is pass-by-value, it's almost certainly being used as a pointer @@ -701,6 +730,7 @@ static void count_agg_clauses_walker_isa(Node* node, count_agg_clauses_context* */ costs->transitionSpace += ALLOCSET_DEFAULT_INITSIZE; costs->aggWidth += ALLOCSET_DEFAULT_INITSIZE; +#endif } else { costs->aggWidth += get_typavgwidth(aggtranstype, -1); } diff --git a/src/gausskernel/runtime/executor/nodeAgg.cpp b/src/gausskernel/runtime/executor/nodeAgg.cpp index ba75cb659..0bb48f852 100644 --- a/src/gausskernel/runtime/executor/nodeAgg.cpp +++ b/src/gausskernel/runtime/executor/nodeAgg.cpp @@ -2927,6 +2927,13 @@ int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext* aggcontext) *aggcontext = ((WindowAggState*)fcinfo->context)->aggcontext; return AGG_CONTEXT_WINDOW; } +#ifndef ENABLE_MULTIPLE_NODES + if (fcinfo->context && IsA(fcinfo->context, VecWindowAggState)) { + if (aggcontext != NULL) + *aggcontext = ((VecWindowAggState*)fcinfo->context)->aggcontext; + return AGG_CONTEXT_WINDOW; + } +#endif /* this is just to prevent "uninitialized variable" warnings */ if (aggcontext != NULL) diff --git a/src/gausskernel/runtime/vecexecutor/vecfuncache.cpp b/src/gausskernel/runtime/vecexecutor/vecfuncache.cpp index 83948c59c..86f8b1027 100644 --- a/src/gausskernel/runtime/vecexecutor/vecfuncache.cpp +++ b/src/gausskernel/runtime/vecexecutor/vecfuncache.cpp @@ -43,6 +43,12 @@ static VecFuncCacheEntry vec_func_table[] = {{1724, {}, {vnumeric_sum, vnumeric_sum}, {vsnumeric_sum, vsnumeric_sum}}, +#ifndef ENABLE_MULTIPLE_NODES + {5435, /* sum(numeric) */ + {}, + {vnumeric_sum, vnumeric_sum}, + {vsnumeric_sum, vsnumeric_sum}}, +#endif {1726, { vnumeric_op, diff --git a/src/gausskernel/runtime/vecexecutor/vecnode/vecagg.cpp b/src/gausskernel/runtime/vecexecutor/vecnode/vecagg.cpp index 492b8322f..8c3f2600e 100644 --- a/src/gausskernel/runtime/vecexecutor/vecnode/vecagg.cpp +++ b/src/gausskernel/runtime/vecexecutor/vecnode/vecagg.cpp @@ -439,8 +439,13 @@ VecAggState* ExecInitVecAggregation(VecAgg* node, EState* estate, int eflags) if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(aggref->aggfnoid)); - peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn; - peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn; + transfn_oid = aggform->aggtransfn; + finalfn_oid = aggform->aggfinalfn; +#ifndef ENABLE_MULTIPLE_NODES + numeric_aggfn_info_change(aggref->aggfnoid, &transfn_oid, &aggtranstype, &transfn_oid); +#endif + peraggstate->transfn_oid = transfn_oid; + peraggstate->finalfn_oid = finalfn_oid; #ifdef PGXC peraggstate->collectfn_oid = aggform->aggcollectfn; @@ -516,7 +521,9 @@ VecAggState* ExecInitVecAggregation(VecAgg* node, EState* estate, int eflags) * field. Must do it the hard way with SysCacheGetAttr. */ text_init_val = SysCacheGetAttr(AGGFNOID, agg_tuple, Anum_pg_aggregate_agginitval, &peraggstate->initValueIsNull); - +#ifndef ENABLE_MULTIPLE_NODES + peraggstate->initValueIsNull = numeric_agg_trans_initvalisnull(peraggstate->transfn_oid, peraggstate->initValueIsNull); +#endif if (peraggstate->initValueIsNull) peraggstate->initValue = (Datum)0; else @@ -675,8 +682,12 @@ VecAggState* ExecInitVecAggregation(VecAgg* node, EState* estate, int eflags) aggstate->aggInfo[idx].vec_agg_function.flinfo->vec_fn_addr = aggstate->aggInfo[idx].vec_agg_cache[0]; else aggstate->aggInfo[idx].vec_agg_function.flinfo->vec_fn_addr = aggstate->aggInfo[idx].vec_agg_cache[1]; - +#ifdef ENABLE_MULTIPLE_NODES if (OidIsValid(peraggstate->finalfn_oid)) { +#else + if (OidIsValid(peraggstate->finalfn_oid) && aggstate->aggInfo[idx].vec_agg_cache[0] && + aggstate->aggInfo[idx].vec_agg_final[0]) { +#endif InitFunctionCallInfoData(aggstate->aggInfo[idx].vec_final_function, &peraggstate->finalfn, 2, diff --git a/src/gausskernel/runtime/vecexecutor/vecnode/vecwindowagg.cpp b/src/gausskernel/runtime/vecexecutor/vecnode/vecwindowagg.cpp index 1b303a584..e11ca1c35 100644 --- a/src/gausskernel/runtime/vecexecutor/vecnode/vecwindowagg.cpp +++ b/src/gausskernel/runtime/vecexecutor/vecnode/vecwindowagg.cpp @@ -547,8 +547,27 @@ VecWinAggRuntime::VecWinAggRuntime(VecWindowAggState* runtime) : BaseAggRunner() WindowStatePerFunc perfuncstate = &(m_winruntime->perfunc[winfuncno]); DispatchAggFunction(peraggstate, perfuncstate, &runtime->windowAggInfo[i]); - if (m_sortKey > 0) + if (m_sortKey > 0) { m_cellvar_encoded[i] = CheckAggEncoded(peraggstate->transfn.fn_rettype); +#ifndef ENABLE_MULTIPLE_NODES + /* + * fix some case that row agg function has both transfn and finnal + * but vec agg function only have transfn + */ + if (OidIsValid(peraggstate->finalfn.fn_oid) && + runtime->windowAggInfo[i].vec_final_function.flinfo == NULL) { + m_cellvar_encoded[i] = CheckAggEncoded(peraggstate->finalfn.fn_rettype); + } + /* + * in some case, vec agg function has its own rettyp + * XXX: hard code here + */ + if (perfuncstate->flinfo.fn_oid == 2100 || perfuncstate->flinfo.fn_oid == 2103 + || perfuncstate->flinfo.fn_oid == 2717 || perfuncstate->flinfo.fn_oid == 2159) { + m_cellvar_encoded[i] = true; + } +#endif + } } /* agg start from here */ @@ -643,7 +662,11 @@ void VecWinAggRuntime::DispatchWindowFunction(WindowStatePerFunc perfuncstate, i entry = (VecFuncCacheEntry*)hash_search(g_instance.vec_func_hash, &funcoid, HASH_FIND, &found); if (found) { +#ifdef ENABLE_MULTIPLE_NODES InitFunctionCallInfoData(m_windowFunc[i], &perfuncstate->flinfo, 2, perfuncstate->winCollation, NULL, NULL); +#else + InitFunctionCallInfoData(m_windowFunc[i], &perfuncstate->flinfo, 2, perfuncstate->winCollation, (Node *)m_winruntime, NULL); +#endif if (m_aggNum == 0 || m_sortKey == 0) m_windowFunc[i].flinfo->vec_fn_addr = entry->vec_fn_cache[0]; @@ -680,17 +703,28 @@ void VecWinAggRuntime::DispatchAggFunction( entry = (VecFuncCacheEntry*)hash_search(g_instance.vec_func_hash, &transfn_oid, HASH_FIND, &found); if (found) { +#ifdef ENABLE_MULTIPLE_NODES InitFunctionCallInfoData( aggInfo->vec_agg_function, &peraggState->transfn, 2, perfuncstate->winCollation, NULL, NULL); +#else + InitFunctionCallInfoData( + aggInfo->vec_agg_function, &peraggState->transfn, 2, perfuncstate->winCollation, (Node*)m_winruntime, NULL); +#endif aggInfo->vec_agg_cache = &entry->vec_agg_cache[0]; aggInfo->vec_agg_final = &entry->vec_transform_function[0]; aggInfo->vec_agg_function.flinfo->vec_fn_addr = aggInfo->vec_agg_cache[0]; +#ifdef ENABLE_MULTIPLE_NODES if (OidIsValid(peraggState->finalfn_oid)) { InitFunctionCallInfoData( aggInfo->vec_final_function, &peraggState->finalfn, 2, perfuncstate->winCollation, NULL, NULL); +#else + if (OidIsValid(peraggState->finalfn_oid) && aggInfo->vec_agg_final[0]) { + InitFunctionCallInfoData( + aggInfo->vec_final_function, &peraggState->finalfn, 2, perfuncstate->winCollation, (Node*)m_winruntime, NULL); +#endif aggInfo->vec_final_function.flinfo->fn_addr = aggInfo->vec_agg_final[0]; } } else { diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_845.sql b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_845.sql new file mode 100644 index 000000000..87889c7e0 --- /dev/null +++ b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_845.sql @@ -0,0 +1,17 @@ +DROP FUNCTION IF EXISTS pg_catalog.numeric_sum; + +DROP FUNCTION IF EXISTS pg_catalog.int8_avg_accum_numeric; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_accum_numeric; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_avg_numeric; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_avg_accum_numeric; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_stddev_pop_numeric; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_stddev_samp_numeric; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_var_pop_numeric; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_var_samp_numeric; \ No newline at end of file diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_845.sql b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_845.sql new file mode 100644 index 000000000..87889c7e0 --- /dev/null +++ b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_845.sql @@ -0,0 +1,17 @@ +DROP FUNCTION IF EXISTS pg_catalog.numeric_sum; + +DROP FUNCTION IF EXISTS pg_catalog.int8_avg_accum_numeric; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_accum_numeric; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_avg_numeric; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_avg_accum_numeric; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_stddev_pop_numeric; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_stddev_samp_numeric; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_var_pop_numeric; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_var_samp_numeric; \ No newline at end of file diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_845.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_845.sql new file mode 100644 index 000000000..b1e47c830 --- /dev/null +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_845.sql @@ -0,0 +1,62 @@ +DROP FUNCTION IF EXISTS pg_catalog.numeric_sum; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5435; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_sum(internal) +RETURNS numeric +LANGUAGE internal +AS 'numeric_sum'; + +DROP FUNCTION IF EXISTS pg_catalog.int8_avg_accum_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5439; +CREATE OR REPLACE FUNCTION pg_catalog.int8_avg_accum_numeric(internal, int8) +RETURNS internal +LANGUAGE internal +AS 'int8_avg_accum_numeric'; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_accum_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5440; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_accum_numeric(internal, numeric) +RETURNS internal +LANGUAGE internal +AS 'numeric_accum_numeric'; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_avg_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5441; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_avg_numeric(internal) +RETURNS numeric +LANGUAGE internal +AS 'numeric_avg_numeric'; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_avg_accum_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5442; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_avg_accum_numeric(internal, numeric) +RETURNS _numeric +LANGUAGE internal +AS 'numeric_avg_accum_numeric'; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_stddev_pop_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5443; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_stddev_pop_numeric(internal) +RETURNS numeric +LANGUAGE internal +AS 'numeric_stddev_pop_numeric'; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_stddev_samp_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5444; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_stddev_samp_numeric(internal) +RETURNS numeric +LANGUAGE internal +AS 'numeric_stddev_samp_numeric'; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_var_pop_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5445; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_var_pop_numeric(internal) +RETURNS numeric +LANGUAGE internal +AS 'numeric_var_pop_numeric'; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_var_samp_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5446; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_var_samp_numeric(numeric) +RETURNS varchar +LANGUAGE internal +AS 'numeric_var_samp_numeric'; \ No newline at end of file diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_845.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_845.sql new file mode 100644 index 000000000..b1e47c830 --- /dev/null +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_845.sql @@ -0,0 +1,62 @@ +DROP FUNCTION IF EXISTS pg_catalog.numeric_sum; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5435; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_sum(internal) +RETURNS numeric +LANGUAGE internal +AS 'numeric_sum'; + +DROP FUNCTION IF EXISTS pg_catalog.int8_avg_accum_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5439; +CREATE OR REPLACE FUNCTION pg_catalog.int8_avg_accum_numeric(internal, int8) +RETURNS internal +LANGUAGE internal +AS 'int8_avg_accum_numeric'; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_accum_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5440; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_accum_numeric(internal, numeric) +RETURNS internal +LANGUAGE internal +AS 'numeric_accum_numeric'; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_avg_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5441; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_avg_numeric(internal) +RETURNS numeric +LANGUAGE internal +AS 'numeric_avg_numeric'; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_avg_accum_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5442; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_avg_accum_numeric(internal, numeric) +RETURNS _numeric +LANGUAGE internal +AS 'numeric_avg_accum_numeric'; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_stddev_pop_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5443; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_stddev_pop_numeric(internal) +RETURNS numeric +LANGUAGE internal +AS 'numeric_stddev_pop_numeric'; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_stddev_samp_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5444; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_stddev_samp_numeric(internal) +RETURNS numeric +LANGUAGE internal +AS 'numeric_stddev_samp_numeric'; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_var_pop_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5445; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_var_pop_numeric(internal) +RETURNS numeric +LANGUAGE internal +AS 'numeric_var_pop_numeric'; + +DROP FUNCTION IF EXISTS pg_catalog.numeric_var_samp_numeric; +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5446; +CREATE OR REPLACE FUNCTION pg_catalog.numeric_var_samp_numeric(numeric) +RETURNS varchar +LANGUAGE internal +AS 'numeric_var_samp_numeric'; \ No newline at end of file diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 9ce8ac839..76b0bce30 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -1348,6 +1348,17 @@ extern Datum int8_avg_accum(PG_FUNCTION_ARGS); #ifdef PGXC extern Datum numeric_avg_collect(PG_FUNCTION_ARGS); #endif +#ifndef ENABLE_MULTIPLE_NODES +extern Datum int8_avg_accum_numeric(PG_FUNCTION_ARGS); +extern Datum numeric_sum(PG_FUNCTION_ARGS); +extern Datum numeric_accum_numeric(PG_FUNCTION_ARGS); +extern Datum numeric_avg_numeric(PG_FUNCTION_ARGS); +extern Datum numeric_avg_accum_numeric(PG_FUNCTION_ARGS); +extern Datum numeric_var_pop_numeric(PG_FUNCTION_ARGS); +extern Datum numeric_var_samp_numeric(PG_FUNCTION_ARGS); +extern Datum numeric_stddev_pop_numeric(PG_FUNCTION_ARGS); +extern Datum numeric_stddev_samp_numeric(PG_FUNCTION_ARGS); +#endif extern Datum numeric_avg(PG_FUNCTION_ARGS); extern Datum numeric_var_pop(PG_FUNCTION_ARGS); extern Datum numeric_var_samp(PG_FUNCTION_ARGS); diff --git a/src/include/utils/numeric.h b/src/include/utils/numeric.h index d5472f53a..63b4e86e4 100644 --- a/src/include/utils/numeric.h +++ b/src/include/utils/numeric.h @@ -352,4 +352,9 @@ extern void int64_to_numericvar(int64 val, NumericVar *var); extern void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result); extern char *numeric_normalize(Numeric num); +bool numeric_agg_trans_initvalisnull(Oid transfn_oid, bool initvalisnull); +void numeric_transfn_info_change(Oid aggfn_oid, Oid *transfn_oid, Oid *transtype); +void numeric_finalfn_info_change(Oid aggdn_oid, Oid *finalfn_oid); +void numeric_aggfn_info_change(Oid aggfn_oid, Oid *transfn_oid, Oid *transtype, Oid *finalfn_oid); + #endif /* _PG_NUMERIC_H_ */