diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index 91df184..4a4ca5d 100644 *** a/src/backend/utils/adt/arrayfuncs.c --- b/src/backend/utils/adt/arrayfuncs.c *************** array_larger(PG_FUNCTION_ARGS) *** 4714,4719 **** --- 4714,4737 ---- } Datum + array_larger_inv(PG_FUNCTION_ARGS) + { + ArrayType *v1, + *v2; + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function function called in non-aggregate context"); + + v1 = PG_GETARG_ARRAYTYPE_P(0); + v2 = PG_GETARG_ARRAYTYPE_P(1); + + if (array_cmp(fcinfo) > 0) + PG_RETURN_ARRAYTYPE_P(v1); + PG_RETURN_NULL(); + } + + + Datum array_smaller(PG_FUNCTION_ARGS) { ArrayType *v1, *************** array_smaller(PG_FUNCTION_ARGS) *** 4728,4733 **** --- 4746,4767 ---- PG_RETURN_ARRAYTYPE_P(result); } + Datum + array_smaller_inv(PG_FUNCTION_ARGS) + { + ArrayType *v1, + *v2; + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function function called in non-aggregate context"); + + v1 = PG_GETARG_ARRAYTYPE_P(0); + v2 = PG_GETARG_ARRAYTYPE_P(1); + + if (array_cmp(fcinfo) < 0) + PG_RETURN_ARRAYTYPE_P(v1); + PG_RETURN_NULL(); + } typedef struct generate_subscripts_fctx { diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c index 0158758..cba17a3 100644 *** a/src/backend/utils/adt/cash.c --- b/src/backend/utils/adt/cash.c *************** cashlarger(PG_FUNCTION_ARGS) *** 877,882 **** --- 877,896 ---- PG_RETURN_CASH(result); } + Datum + cashlarger_inv(PG_FUNCTION_ARGS) + { + Cash c1 = PG_GETARG_CASH(0); + Cash c2 = PG_GETARG_CASH(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (c1 > c2) + PG_RETURN_CASH(c1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + /* cashsmaller() * Return smaller of two cash values. */ *************** cashsmaller(PG_FUNCTION_ARGS) *** 892,897 **** --- 906,925 ---- PG_RETURN_CASH(result); } + Datum + cashsmaller_inv(PG_FUNCTION_ARGS) + { + Cash c1 = PG_GETARG_CASH(0); + Cash c2 = PG_GETARG_CASH(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (c1 < c2) + PG_RETURN_CASH(c1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + /* cash_words() * This converts a int4 as well but to a representation using words * Obviously way North American centric - sorry diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index 06cc0cd..0cca0b0 100644 *** a/src/backend/utils/adt/date.c --- b/src/backend/utils/adt/date.c *************** date_larger(PG_FUNCTION_ARGS) *** 396,401 **** --- 396,415 ---- } Datum + date_larger_inv(PG_FUNCTION_ARGS) + { + DateADT dateVal1 = PG_GETARG_DATEADT(0); + DateADT dateVal2 = PG_GETARG_DATEADT(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (dateVal1 > dateVal2) + PG_RETURN_DATEADT(dateVal1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + + Datum date_smaller(PG_FUNCTION_ARGS) { DateADT dateVal1 = PG_GETARG_DATEADT(0); *************** date_smaller(PG_FUNCTION_ARGS) *** 404,409 **** --- 418,437 ---- PG_RETURN_DATEADT((dateVal1 < dateVal2) ? dateVal1 : dateVal2); } + Datum + date_smaller_inv(PG_FUNCTION_ARGS) + { + DateADT dateVal1 = PG_GETARG_DATEADT(0); + DateADT dateVal2 = PG_GETARG_DATEADT(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (dateVal1 < dateVal2) + PG_RETURN_DATEADT(dateVal1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + /* Compute difference between two dates in days. */ Datum *************** time_larger(PG_FUNCTION_ARGS) *** 1463,1468 **** --- 1491,1510 ---- } Datum + time_larger_inv(PG_FUNCTION_ARGS) + { + TimeADT time1 = PG_GETARG_TIMEADT(0); + TimeADT time2 = PG_GETARG_TIMEADT(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (time1 > time2) + PG_RETURN_TIMEADT(time1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + + Datum time_smaller(PG_FUNCTION_ARGS) { TimeADT time1 = PG_GETARG_TIMEADT(0); *************** time_smaller(PG_FUNCTION_ARGS) *** 1471,1476 **** --- 1513,1532 ---- PG_RETURN_TIMEADT((time1 < time2) ? time1 : time2); } + Datum + time_smaller_inv(PG_FUNCTION_ARGS) + { + TimeADT time1 = PG_GETARG_TIMEADT(0); + TimeADT time2 = PG_GETARG_TIMEADT(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (time1 < time2) + PG_RETURN_TIMEADT(time1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + /* overlaps_time() --- implements the SQL OVERLAPS operator. * * Algorithm is per SQL spec. This is much harder than you'd think *************** timetz_larger(PG_FUNCTION_ARGS) *** 2262,2267 **** --- 2318,2337 ---- } Datum + timetz_larger_inv(PG_FUNCTION_ARGS) + { + TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); + TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (timetz_cmp_internal(time1, time2) > 0) + PG_RETURN_TIMETZADT_P(time1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + + Datum timetz_smaller(PG_FUNCTION_ARGS) { TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); *************** timetz_smaller(PG_FUNCTION_ARGS) *** 2275,2280 **** --- 2345,2364 ---- PG_RETURN_TIMETZADT_P(result); } + Datum + timetz_smaller_inv(PG_FUNCTION_ARGS) + { + TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); + TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (timetz_cmp_internal(time1, time2) < 0) + PG_RETURN_TIMETZADT_P(time1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + /* timetz_pl_interval() * Add interval to timetz. */ diff --git a/src/backend/utils/adt/enum.c b/src/backend/utils/adt/enum.c index 83c3878..32035e0 100644 *** a/src/backend/utils/adt/enum.c --- b/src/backend/utils/adt/enum.c *************** enum_smaller(PG_FUNCTION_ARGS) *** 273,278 **** --- 273,292 ---- } Datum + enum_smaller_inv(PG_FUNCTION_ARGS) + { + Oid a = PG_GETARG_OID(0); + Oid b = PG_GETARG_OID(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (enum_cmp_internal(a, b, fcinfo) < 0) + PG_RETURN_OID(a); + PG_RETURN_NULL(); + } + + Datum enum_larger(PG_FUNCTION_ARGS) { Oid a = PG_GETARG_OID(0); *************** enum_larger(PG_FUNCTION_ARGS) *** 282,287 **** --- 296,315 ---- } Datum + enum_larger_inv(PG_FUNCTION_ARGS) + { + Oid a = PG_GETARG_OID(0); + Oid b = PG_GETARG_OID(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (enum_cmp_internal(a, b, fcinfo) > 0) + PG_RETURN_OID(a); + PG_RETURN_NULL(); + } + + Datum enum_cmp(PG_FUNCTION_ARGS) { Oid a = PG_GETARG_OID(0); diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index 774267e..04f89b0 100644 *** a/src/backend/utils/adt/float.c --- b/src/backend/utils/adt/float.c *************** float4larger(PG_FUNCTION_ARGS) *** 637,642 **** --- 637,658 ---- } Datum + float4larger_inv(PG_FUNCTION_ARGS) + { + float4 arg1 = PG_GETARG_FLOAT4(0); + float4 arg2 = PG_GETARG_FLOAT4(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (isnan(arg1) || isnan(arg2)) + PG_RETURN_NULL(); + else if (float4_cmp_internal(arg1, arg2) > 0) + PG_RETURN_FLOAT4(arg1); + PG_RETURN_NULL(); + } + + Datum float4smaller(PG_FUNCTION_ARGS) { float4 arg1 = PG_GETARG_FLOAT4(0); *************** float4smaller(PG_FUNCTION_ARGS) *** 650,655 **** --- 666,687 ---- PG_RETURN_FLOAT4(result); } + Datum + float4smaller_inv(PG_FUNCTION_ARGS) + { + float4 arg1 = PG_GETARG_FLOAT4(0); + float4 arg2 = PG_GETARG_FLOAT4(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (isnan(arg1) || isnan(arg2)) + PG_RETURN_NULL(); + else if (float4_cmp_internal(arg1, arg2) < 0) + PG_RETURN_FLOAT4(arg1); + PG_RETURN_NULL(); + } + /* * ====================== * FLOAT8 BASE OPERATIONS *************** float8larger(PG_FUNCTION_ARGS) *** 704,709 **** --- 736,757 ---- } Datum + float8larger_inv(PG_FUNCTION_ARGS) + { + float8 arg1 = PG_GETARG_FLOAT8(0); + float8 arg2 = PG_GETARG_FLOAT8(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (isnan(arg1) || isnan(arg2)) + PG_RETURN_NULL(); + else if (float8_cmp_internal(arg1, arg2) > 0) + PG_RETURN_FLOAT8(arg1); + PG_RETURN_NULL(); + } + + Datum float8smaller(PG_FUNCTION_ARGS) { float8 arg1 = PG_GETARG_FLOAT8(0); *************** float8smaller(PG_FUNCTION_ARGS) *** 717,722 **** --- 765,785 ---- PG_RETURN_FLOAT8(result); } + Datum + float8smaller_inv(PG_FUNCTION_ARGS) + { + float8 arg1 = PG_GETARG_FLOAT8(0); + float8 arg2 = PG_GETARG_FLOAT8(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (isnan(arg1) || isnan(arg2)) + PG_RETURN_NULL(); + else if (float8_cmp_internal(arg1, arg2) < 0) + PG_RETURN_FLOAT8(arg1); + PG_RETURN_NULL(); + } /* * ==================== diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c index 669355e..fe9d736 100644 *** a/src/backend/utils/adt/int.c --- b/src/backend/utils/adt/int.c *************** int2larger(PG_FUNCTION_ARGS) *** 1185,1190 **** --- 1185,1204 ---- } Datum + int2larger_inv(PG_FUNCTION_ARGS) + { + int16 arg1 = PG_GETARG_INT16(0); + int16 arg2 = PG_GETARG_INT16(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (arg1 > arg2) + PG_RETURN_INT16(arg1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + + Datum int2smaller(PG_FUNCTION_ARGS) { int16 arg1 = PG_GETARG_INT16(0); *************** int2smaller(PG_FUNCTION_ARGS) *** 1194,1199 **** --- 1208,1227 ---- } Datum + int2smaller_inv(PG_FUNCTION_ARGS) + { + int16 arg1 = PG_GETARG_INT16(0); + int16 arg2 = PG_GETARG_INT16(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (arg1 < arg2) + PG_RETURN_INT16(arg1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + + Datum int4larger(PG_FUNCTION_ARGS) { int32 arg1 = PG_GETARG_INT32(0); *************** int4larger(PG_FUNCTION_ARGS) *** 1203,1208 **** --- 1231,1250 ---- } Datum + int4larger_inv(PG_FUNCTION_ARGS) + { + int32 arg1 = PG_GETARG_INT32(0); + int32 arg2 = PG_GETARG_INT32(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (arg1 > arg2) + PG_RETURN_INT32(arg1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + + Datum int4smaller(PG_FUNCTION_ARGS) { int32 arg1 = PG_GETARG_INT32(0); *************** int4smaller(PG_FUNCTION_ARGS) *** 1211,1216 **** --- 1253,1272 ---- PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2); } + Datum + int4smaller_inv(PG_FUNCTION_ARGS) + { + int32 arg1 = PG_GETARG_INT32(0); + int32 arg2 = PG_GETARG_INT32(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (arg1 < arg2) + PG_RETURN_INT32(arg1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + /* * Bit-pushing operators * diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c index 5e1be90..820be68 100644 *** a/src/backend/utils/adt/int8.c --- b/src/backend/utils/adt/int8.c *************** int8larger(PG_FUNCTION_ARGS) *** 752,757 **** --- 752,771 ---- } Datum + int8larger_inv(PG_FUNCTION_ARGS) + { + int64 arg1 = PG_GETARG_INT64(0); + int64 arg2 = PG_GETARG_INT64(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (arg1 > arg2) + PG_RETURN_INT64(arg1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + + Datum int8smaller(PG_FUNCTION_ARGS) { int64 arg1 = PG_GETARG_INT64(0); *************** int8smaller(PG_FUNCTION_ARGS) *** 764,769 **** --- 778,797 ---- } Datum + int8smaller_inv(PG_FUNCTION_ARGS) + { + int64 arg1 = PG_GETARG_INT64(0); + int64 arg2 = PG_GETARG_INT64(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (arg1 < arg2) + PG_RETURN_INT64(arg1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + + Datum int84pl(PG_FUNCTION_ARGS) { int64 arg1 = PG_GETARG_INT64(0); diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index 64eb0f8..c9500bf 100644 *** a/src/backend/utils/adt/numeric.c --- b/src/backend/utils/adt/numeric.c *************** numeric_smaller(PG_FUNCTION_ARGS) *** 1872,1877 **** --- 1872,1892 ---- PG_RETURN_NUMERIC(num2); } + Datum + numeric_smaller_inv(PG_FUNCTION_ARGS) + { + Numeric num1 = PG_GETARG_NUMERIC(0); + Numeric num2 = PG_GETARG_NUMERIC(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2)) + PG_RETURN_NULL(); + else if (cmp_numerics(num1, num2) < 0) + PG_RETURN_NUMERIC(num1); + PG_RETURN_NULL(); + } /* * numeric_larger() - *************** numeric_larger(PG_FUNCTION_ARGS) *** 1894,1899 **** --- 1909,1930 ---- PG_RETURN_NUMERIC(num2); } + Datum + numeric_larger_inv(PG_FUNCTION_ARGS) + { + Numeric num1 = PG_GETARG_NUMERIC(0); + Numeric num2 = PG_GETARG_NUMERIC(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2)) + PG_RETURN_NULL(); + else if (cmp_numerics(num1, num2) > 0) + PG_RETURN_NUMERIC(num1); + PG_RETURN_NULL(); + } + /* ---------------------------------------------------------------------- * diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c index 8945ef4..745449a 100644 *** a/src/backend/utils/adt/oid.c --- b/src/backend/utils/adt/oid.c *************** oidlarger(PG_FUNCTION_ARGS) *** 397,402 **** --- 397,416 ---- } Datum + oidlarger_inv(PG_FUNCTION_ARGS) + { + Oid arg1 = PG_GETARG_OID(0); + Oid arg2 = PG_GETARG_OID(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (arg1 > arg2) + PG_RETURN_OID(arg1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + + Datum oidsmaller(PG_FUNCTION_ARGS) { Oid arg1 = PG_GETARG_OID(0); *************** oidsmaller(PG_FUNCTION_ARGS) *** 406,411 **** --- 420,439 ---- } Datum + oidsmaller_inv(PG_FUNCTION_ARGS) + { + Oid arg1 = PG_GETARG_OID(0); + Oid arg2 = PG_GETARG_OID(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (arg1 < arg2) + PG_RETURN_OID(arg1); + PG_RETURN_NULL(); /* Unable to perform inverse transition */ + } + + Datum oidvectoreq(PG_FUNCTION_ARGS) { int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo)); diff --git a/src/backend/utils/adt/tid.c b/src/backend/utils/adt/tid.c index 6e2bbdc..57fcf80 100644 *** a/src/backend/utils/adt/tid.c --- b/src/backend/utils/adt/tid.c *************** tidlarger(PG_FUNCTION_ARGS) *** 237,242 **** --- 237,256 ---- } Datum + tidlarger_inv(PG_FUNCTION_ARGS) + { + ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0); + ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (ItemPointerCompare(arg1, arg2) > 0) + PG_RETURN_ITEMPOINTER(arg1); + PG_RETURN_NULL(); + } + + Datum tidsmaller(PG_FUNCTION_ARGS) { ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0); *************** tidsmaller(PG_FUNCTION_ARGS) *** 245,250 **** --- 259,277 ---- PG_RETURN_ITEMPOINTER(ItemPointerCompare(arg1, arg2) <= 0 ? arg1 : arg2); } + Datum + tidsmaller_inv(PG_FUNCTION_ARGS) + { + ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0); + ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (ItemPointerCompare(arg1, arg2) < 0) + PG_RETURN_ITEMPOINTER(arg1); + PG_RETURN_NULL(); + } /* * Functions to get latest tid of a specified tuple. diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index ce30bb6..e611983 100644 *** a/src/backend/utils/adt/timestamp.c --- b/src/backend/utils/adt/timestamp.c *************** timestamp_smaller(PG_FUNCTION_ARGS) *** 2682,2687 **** --- 2682,2701 ---- } Datum + timestamp_smaller_inv(PG_FUNCTION_ARGS) + { + Timestamp dt1 = PG_GETARG_TIMESTAMP(0); + Timestamp dt2 = PG_GETARG_TIMESTAMP(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (timestamp_cmp_internal(dt1, dt2) < 0) + PG_RETURN_TIMESTAMP(dt1); + PG_RETURN_NULL(); + } + + Datum timestamp_larger(PG_FUNCTION_ARGS) { Timestamp dt1 = PG_GETARG_TIMESTAMP(0); *************** timestamp_larger(PG_FUNCTION_ARGS) *** 2695,2700 **** --- 2709,2727 ---- PG_RETURN_TIMESTAMP(result); } + Datum + timestamp_larger_inv(PG_FUNCTION_ARGS) + { + Timestamp dt1 = PG_GETARG_TIMESTAMP(0); + Timestamp dt2 = PG_GETARG_TIMESTAMP(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (timestamp_cmp_internal(dt1, dt2) > 0) + PG_RETURN_TIMESTAMP(dt1); + PG_RETURN_NULL(); + } Datum timestamp_mi(PG_FUNCTION_ARGS) *************** interval_smaller(PG_FUNCTION_ARGS) *** 3151,3156 **** --- 3178,3197 ---- } Datum + interval_smaller_inv(PG_FUNCTION_ARGS) + { + Interval *interval1 = PG_GETARG_INTERVAL_P(0); + Interval *interval2 = PG_GETARG_INTERVAL_P(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (interval_cmp_internal(interval1, interval2) < 0) + PG_RETURN_INTERVAL_P(interval1); + PG_RETURN_NULL(); + } + + Datum interval_larger(PG_FUNCTION_ARGS) { Interval *interval1 = PG_GETARG_INTERVAL_P(0); *************** interval_larger(PG_FUNCTION_ARGS) *** 3165,3170 **** --- 3206,3225 ---- } Datum + interval_larger_inv(PG_FUNCTION_ARGS) + { + Interval *interval1 = PG_GETARG_INTERVAL_P(0); + Interval *interval2 = PG_GETARG_INTERVAL_P(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (interval_cmp_internal(interval1, interval2) > 0) + PG_RETURN_INTERVAL_P(interval1); + PG_RETURN_NULL(); + } + + Datum interval_pl(PG_FUNCTION_ARGS) { Interval *span1 = PG_GETARG_INTERVAL_P(0); diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c index 502ca44..536ca66 100644 *** a/src/backend/utils/adt/varchar.c --- b/src/backend/utils/adt/varchar.c *************** bpchar_larger(PG_FUNCTION_ARGS) *** 877,882 **** --- 877,905 ---- } Datum + bpchar_larger_inv(PG_FUNCTION_ARGS) + { + BpChar *arg1 = PG_GETARG_BPCHAR_PP(0); + BpChar *arg2 = PG_GETARG_BPCHAR_PP(1); + int len1, + len2; + int cmp; + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + len1 = bcTruelen(arg1); + len2 = bcTruelen(arg2); + + cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2, + PG_GET_COLLATION()); + + if (cmp > 0) + PG_RETURN_BPCHAR_P(arg1); + PG_RETURN_NULL(); + } + + Datum bpchar_smaller(PG_FUNCTION_ARGS) { BpChar *arg1 = PG_GETARG_BPCHAR_PP(0); *************** bpchar_smaller(PG_FUNCTION_ARGS) *** 894,899 **** --- 917,945 ---- PG_RETURN_BPCHAR_P((cmp <= 0) ? arg1 : arg2); } + Datum + bpchar_smaller_inv(PG_FUNCTION_ARGS) + { + BpChar *arg1 = PG_GETARG_BPCHAR_PP(0); + BpChar *arg2 = PG_GETARG_BPCHAR_PP(1); + int len1, + len2; + int cmp; + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + len1 = bcTruelen(arg1); + len2 = bcTruelen(arg2); + + cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2, + PG_GET_COLLATION()); + + if (cmp < 0) + PG_RETURN_BPCHAR_P(arg1); + PG_RETURN_NULL(); + } + /* * bpchar needs a specialized hash function because we want to ignore diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index cb07a06..821cded 100644 *** a/src/backend/utils/adt/varlena.c --- b/src/backend/utils/adt/varlena.c *************** text_larger(PG_FUNCTION_ARGS) *** 1697,1702 **** --- 1697,1716 ---- } Datum + text_larger_inv(PG_FUNCTION_ARGS) + { + text *arg1 = PG_GETARG_TEXT_PP(0); + text *arg2 = PG_GETARG_TEXT_PP(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (text_cmp(arg1, arg2, PG_GET_COLLATION()) > 0) + PG_RETURN_TEXT_P(arg1); + PG_RETURN_NULL(); + } + + Datum text_smaller(PG_FUNCTION_ARGS) { text *arg1 = PG_GETARG_TEXT_PP(0); *************** text_smaller(PG_FUNCTION_ARGS) *** 1708,1713 **** --- 1722,1740 ---- PG_RETURN_TEXT_P(result); } + Datum + text_smaller_inv(PG_FUNCTION_ARGS) + { + text *arg1 = PG_GETARG_TEXT_PP(0); + text *arg2 = PG_GETARG_TEXT_PP(1); + + if (!AggCheckCallContext(fcinfo, NULL)) + elog(ERROR, "aggregate inverse transition function called in non-aggregate context"); + + if (text_cmp(arg1, arg2, PG_GET_COLLATION()) < 0) + PG_RETURN_TEXT_P(arg1); + PG_RETURN_NULL(); + } /* * The following operators support character-by-character comparison diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h index 3412661..f1a602d 100644 *** a/src/include/catalog/pg_aggregate.h --- b/src/include/catalog/pg_aggregate.h *************** DATA(insert ( 2113 n 0 interval_pl - - *** 122,169 **** DATA(insert ( 2114 n 0 numeric_avg_accum - numeric_sum 0 2281 128 _null_ )); /* max */ ! DATA(insert ( 2115 n 0 int8larger - - 413 20 0 _null_ )); ! DATA(insert ( 2116 n 0 int4larger - - 521 23 0 _null_ )); ! DATA(insert ( 2117 n 0 int2larger - - 520 21 0 _null_ )); ! DATA(insert ( 2118 n 0 oidlarger - - 610 26 0 _null_ )); ! DATA(insert ( 2119 n 0 float4larger - - 623 700 0 _null_ )); ! DATA(insert ( 2120 n 0 float8larger - - 674 701 0 _null_ )); ! DATA(insert ( 2121 n 0 int4larger - - 563 702 0 _null_ )); ! DATA(insert ( 2122 n 0 date_larger - - 1097 1082 0 _null_ )); ! DATA(insert ( 2123 n 0 time_larger - - 1112 1083 0 _null_ )); ! DATA(insert ( 2124 n 0 timetz_larger - - 1554 1266 0 _null_ )); ! DATA(insert ( 2125 n 0 cashlarger - - 903 790 0 _null_ )); ! DATA(insert ( 2126 n 0 timestamp_larger - - 2064 1114 0 _null_ )); ! DATA(insert ( 2127 n 0 timestamptz_larger - - 1324 1184 0 _null_ )); ! DATA(insert ( 2128 n 0 interval_larger - - 1334 1186 0 _null_ )); ! DATA(insert ( 2129 n 0 text_larger - - 666 25 0 _null_ )); ! DATA(insert ( 2130 n 0 numeric_larger - - 1756 1700 0 _null_ )); ! DATA(insert ( 2050 n 0 array_larger - - 1073 2277 0 _null_ )); ! DATA(insert ( 2244 n 0 bpchar_larger - - 1060 1042 0 _null_ )); ! DATA(insert ( 2797 n 0 tidlarger - - 2800 27 0 _null_ )); ! DATA(insert ( 3526 n 0 enum_larger - - 3519 3500 0 _null_ )); /* min */ ! DATA(insert ( 2131 n 0 int8smaller - - 412 20 0 _null_ )); ! DATA(insert ( 2132 n 0 int4smaller - - 97 23 0 _null_ )); ! DATA(insert ( 2133 n 0 int2smaller - - 95 21 0 _null_ )); ! DATA(insert ( 2134 n 0 oidsmaller - - 609 26 0 _null_ )); ! DATA(insert ( 2135 n 0 float4smaller - - 622 700 0 _null_ )); ! DATA(insert ( 2136 n 0 float8smaller - - 672 701 0 _null_ )); ! DATA(insert ( 2137 n 0 int4smaller - - 562 702 0 _null_ )); ! DATA(insert ( 2138 n 0 date_smaller - - 1095 1082 0 _null_ )); ! DATA(insert ( 2139 n 0 time_smaller - - 1110 1083 0 _null_ )); ! DATA(insert ( 2140 n 0 timetz_smaller - - 1552 1266 0 _null_ )); ! DATA(insert ( 2141 n 0 cashsmaller - - 902 790 0 _null_ )); ! DATA(insert ( 2142 n 0 timestamp_smaller - - 2062 1114 0 _null_ )); ! DATA(insert ( 2143 n 0 timestamptz_smaller - - 1322 1184 0 _null_ )); ! DATA(insert ( 2144 n 0 interval_smaller - - 1332 1186 0 _null_ )); ! DATA(insert ( 2145 n 0 text_smaller - - 664 25 0 _null_ )); ! DATA(insert ( 2146 n 0 numeric_smaller - - 1754 1700 0 _null_ )); ! DATA(insert ( 2051 n 0 array_smaller - - 1072 2277 0 _null_ )); ! DATA(insert ( 2245 n 0 bpchar_smaller - - 1058 1042 0 _null_ )); ! DATA(insert ( 2798 n 0 tidsmaller - - 2799 27 0 _null_ )); ! DATA(insert ( 3527 n 0 enum_smaller - - 3518 3500 0 _null_ )); /* count */ DATA(insert ( 2147 n 0 int8inc_any - - 0 20 0 "0" )); --- 122,169 ---- DATA(insert ( 2114 n 0 numeric_avg_accum - numeric_sum 0 2281 128 _null_ )); /* max */ ! DATA(insert ( 2115 n 0 int8larger int8larger_inv - 413 20 0 _null_ )); ! DATA(insert ( 2116 n 0 int4larger int4larger_inv - 521 23 0 _null_ )); ! DATA(insert ( 2117 n 0 int2larger int2larger_inv - 520 21 0 _null_ )); ! DATA(insert ( 2118 n 0 oidlarger oidlarger_inv - 610 26 0 _null_ )); ! DATA(insert ( 2119 n 0 float4larger float4larger_inv - 623 700 0 _null_ )); ! DATA(insert ( 2120 n 0 float8larger float8larger_inv - 674 701 0 _null_ )); ! DATA(insert ( 2121 n 0 int4larger int4larger_inv - 563 702 0 _null_ )); ! DATA(insert ( 2122 n 0 date_larger date_larger_inv - 1097 1082 0 _null_ )); ! DATA(insert ( 2123 n 0 time_larger time_larger_inv - 1112 1083 0 _null_ )); ! DATA(insert ( 2124 n 0 timetz_larger timetz_larger_inv - 1554 1266 0 _null_ )); ! DATA(insert ( 2125 n 0 cashlarger cashlarger_inv - 903 790 0 _null_ )); ! DATA(insert ( 2126 n 0 timestamp_larger timestamp_larger_inv - 2064 1114 0 _null_ )); ! DATA(insert ( 2127 n 0 timestamptz_larger timestamptz_larger_inv - 1324 1184 0 _null_ )); ! DATA(insert ( 2128 n 0 interval_larger interval_larger_inv - 1334 1186 0 _null_ )); ! DATA(insert ( 2129 n 0 text_larger text_larger_inv - 666 25 0 _null_ )); ! DATA(insert ( 2130 n 0 numeric_larger numeric_larger_inv - 1756 1700 0 _null_ )); ! DATA(insert ( 2050 n 0 array_larger array_larger_inv - 1073 2277 0 _null_ )); ! DATA(insert ( 2244 n 0 bpchar_larger bpchar_larger_inv - 1060 1042 0 _null_ )); ! DATA(insert ( 2797 n 0 tidlarger tidlarger_inv - 2800 27 0 _null_ )); ! DATA(insert ( 3526 n 0 enum_larger enum_larger_inv - 3519 3500 0 _null_ )); /* min */ ! DATA(insert ( 2131 n 0 int8smaller int8smaller_inv - 412 20 0 _null_ )); ! DATA(insert ( 2132 n 0 int4smaller int4smaller_inv - 97 23 0 _null_ )); ! DATA(insert ( 2133 n 0 int2smaller int2smaller_inv - 95 21 0 _null_ )); ! DATA(insert ( 2134 n 0 oidsmaller oidsmaller_inv - 609 26 0 _null_ )); ! DATA(insert ( 2135 n 0 float4smaller float4smaller_inv - 622 700 0 _null_ )); ! DATA(insert ( 2136 n 0 float8smaller float8smaller_inv - 672 701 0 _null_ )); ! DATA(insert ( 2137 n 0 int4smaller int4smaller_inv - 562 702 0 _null_ )); ! DATA(insert ( 2138 n 0 date_smaller date_smaller_inv - 1095 1082 0 _null_ )); ! DATA(insert ( 2139 n 0 time_smaller time_smaller_inv - 1110 1083 0 _null_ )); ! DATA(insert ( 2140 n 0 timetz_smaller timetz_smaller_inv - 1552 1266 0 _null_ )); ! DATA(insert ( 2141 n 0 cashsmaller cashsmaller_inv - 902 790 0 _null_ )); ! DATA(insert ( 2142 n 0 timestamp_smaller timestamp_smaller_inv - 2062 1114 0 _null_ )); ! DATA(insert ( 2143 n 0 timestamptz_smaller timestamptz_smaller_inv - 1322 1184 0 _null_ )); ! DATA(insert ( 2144 n 0 interval_smaller interval_smaller_inv - 1332 1186 0 _null_ )); ! DATA(insert ( 2145 n 0 text_smaller text_smaller_inv - 664 25 0 _null_ )); ! DATA(insert ( 2146 n 0 numeric_smaller numeric_smaller_inv - 1754 1700 0 _null_ )); ! DATA(insert ( 2051 n 0 array_smaller array_smaller_inv - 1072 2277 0 _null_ )); ! DATA(insert ( 2245 n 0 bpchar_smaller bpchar_smaller_inv - 1058 1042 0 _null_ )); ! DATA(insert ( 2798 n 0 tidsmaller tidsmaller_inv - 2799 27 0 _null_ )); ! DATA(insert ( 3527 n 0 enum_smaller enum_smaller_inv - 3518 3500 0 _null_ )); /* count */ DATA(insert ( 2147 n 0 int8inc_any - - 0 20 0 "0" )); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 334e6b8..42dcb27 100644 *** a/src/include/catalog/pg_proc.h --- b/src/include/catalog/pg_proc.h *************** DESCR("larger of two"); *** 367,372 **** --- 367,377 ---- DATA(insert OID = 211 ( float4smaller PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 700 "700 700" _null_ _null_ _null_ _null_ float4smaller _null_ _null_ _null_ )); DESCR("smaller of two"); + DATA(insert OID = 3567 ( float4larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 700 "700 700" _null_ _null_ _null_ _null_ float4larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 3568 ( float4smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 700 "700 700" _null_ _null_ _null_ _null_ float4smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 212 ( int4um PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 23 "23" _null_ _null_ _null_ _null_ int4um _null_ _null_ _null_ )); DATA(insert OID = 213 ( int2um PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 21 "21" _null_ _null_ _null_ _null_ int2um _null_ _null_ _null_ )); *************** DATA(insert OID = 223 ( float8larger *** 386,391 **** --- 391,400 ---- DESCR("larger of two"); DATA(insert OID = 224 ( float8smaller PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "701 701" _null_ _null_ _null_ _null_ float8smaller _null_ _null_ _null_ )); DESCR("smaller of two"); + DATA(insert OID = 3569 ( float8larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "701 701" _null_ _null_ _null_ _null_ float8larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 3570 ( float8smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "701 701" _null_ _null_ _null_ _null_ float8smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); DATA(insert OID = 225 ( lseg_center PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 600 "601" _null_ _null_ _null_ _null_ lseg_center _null_ _null_ _null_ )); DATA(insert OID = 226 ( path_center PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 600 "602" _null_ _null_ _null_ _null_ path_center _null_ _null_ _null_ )); *************** DATA(insert OID = 458 ( text_larger *** 711,716 **** --- 720,729 ---- DESCR("larger of two"); DATA(insert OID = 459 ( text_smaller PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 25 "25 25" _null_ _null_ _null_ _null_ text_smaller _null_ _null_ _null_ )); DESCR("smaller of two"); + DATA(insert OID = 3571 ( text_larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 25 "25 25" _null_ _null_ _null_ _null_ text_larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 3572 ( text_smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 25 "25 25" _null_ _null_ _null_ _null_ text_smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); DATA(insert OID = 460 ( int8in PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 20 "2275" _null_ _null_ _null_ _null_ int8in _null_ _null_ _null_ )); DESCR("I/O"); *************** DATA(insert OID = 515 ( array_larger *** 859,864 **** --- 872,881 ---- DESCR("larger of two"); DATA(insert OID = 516 ( array_smaller PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 2277 "2277 2277" _null_ _null_ _null_ _null_ array_smaller _null_ _null_ _null_ )); DESCR("smaller of two"); + DATA(insert OID = 3573 ( array_larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 2277 "2277 2277" _null_ _null_ _null_ _null_ array_larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 3574 ( array_smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 2277 "2277 2277" _null_ _null_ _null_ _null_ array_smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); DATA(insert OID = 1191 ( generate_subscripts PGNSP PGUID 12 1 1000 0 0 f f f f t t i 3 0 23 "2277 23 16" _null_ _null_ _null_ _null_ generate_subscripts _null_ _null_ _null_ )); DESCR("array subscripts generator"); DATA(insert OID = 1192 ( generate_subscripts PGNSP PGUID 12 1 1000 0 0 f f f f t t i 2 0 23 "2277 23" _null_ _null_ _null_ _null_ generate_subscripts_nodir _null_ _null_ _null_ )); *************** DESCR("larger of two"); *** 913,918 **** --- 930,945 ---- DATA(insert OID = 771 ( int2smaller PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 21 "21 21" _null_ _null_ _null_ _null_ int2smaller _null_ _null_ _null_ )); DESCR("smaller of two"); + DATA(insert OID = 3575 ( int4larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "23 23" _null_ _null_ _null_ _null_ int4larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 3576 ( int4smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "23 23" _null_ _null_ _null_ _null_ int4smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 3577 ( int2larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 21 "21 21" _null_ _null_ _null_ _null_ int2larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 3578 ( int2smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 21 "21 21" _null_ _null_ _null_ _null_ int2smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + + DATA(insert OID = 774 ( gistgettuple PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 16 "2281 2281" _null_ _null_ _null_ _null_ gistgettuple _null_ _null_ _null_ )); DESCR("gist(internal)"); DATA(insert OID = 638 ( gistgetbitmap PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 20 "2281 2281" _null_ _null_ _null_ _null_ gistgetbitmap _null_ _null_ _null_ )); *************** DATA(insert OID = 898 ( cashlarger *** 1003,1008 **** --- 1030,1039 ---- DESCR("larger of two"); DATA(insert OID = 899 ( cashsmaller PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 790 "790 790" _null_ _null_ _null_ _null_ cashsmaller _null_ _null_ _null_ )); DESCR("smaller of two"); + DATA(insert OID = 3579 ( cashlarger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 790 "790 790" _null_ _null_ _null_ _null_ cashlarger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 3580 ( cashsmaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 790 "790 790" _null_ _null_ _null_ _null_ cashsmaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); DATA(insert OID = 919 ( flt8_mul_cash PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 790 "701 790" _null_ _null_ _null_ _null_ flt8_mul_cash _null_ _null_ _null_ )); DATA(insert OID = 935 ( cash_words PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 25 "790" _null_ _null_ _null_ _null_ cash_words _null_ _null_ _null_ )); DESCR("output money amount as words"); *************** DATA(insert OID = 1063 ( bpchar_larger *** 1157,1162 **** --- 1188,1197 ---- DESCR("larger of two"); DATA(insert OID = 1064 ( bpchar_smaller PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1042 "1042 1042" _null_ _null_ _null_ _null_ bpchar_smaller _null_ _null_ _null_ )); DESCR("smaller of two"); + DATA(insert OID = 3581 ( bpchar_larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1042 "1042 1042" _null_ _null_ _null_ _null_ bpchar_larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 3582 ( bpchar_smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1042 "1042 1042" _null_ _null_ _null_ _null_ bpchar_smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); DATA(insert OID = 1078 ( bpcharcmp PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "1042 1042" _null_ _null_ _null_ _null_ bpcharcmp _null_ _null_ _null_ )); DESCR("less-equal-greater"); DATA(insert OID = 1080 ( hashbpchar PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 23 "1042" _null_ _null_ _null_ _null_ hashbpchar _null_ _null_ _null_ )); *************** DATA(insert OID = 1138 ( date_larger *** 1191,1196 **** --- 1226,1235 ---- DESCR("larger of two"); DATA(insert OID = 1139 ( date_smaller PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1082 "1082 1082" _null_ _null_ _null_ _null_ date_smaller _null_ _null_ _null_ )); DESCR("smaller of two"); + DATA(insert OID = 3583 ( date_larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1082 "1082 1082" _null_ _null_ _null_ _null_ date_larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 3584 ( date_smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1082 "1082 1082" _null_ _null_ _null_ _null_ date_smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); DATA(insert OID = 1140 ( date_mi PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "1082 1082" _null_ _null_ _null_ _null_ date_mi _null_ _null_ _null_ )); DATA(insert OID = 1141 ( date_pli PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1082 "1082 23" _null_ _null_ _null_ _null_ date_pli _null_ _null_ _null_ )); DATA(insert OID = 1142 ( date_mii PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1082 "1082 23" _null_ _null_ _null_ _null_ date_mii _null_ _null_ _null_ )); *************** DATA(insert OID = 1195 ( timestamptz_sm *** 1281,1290 **** --- 1320,1339 ---- DESCR("smaller of two"); DATA(insert OID = 1196 ( timestamptz_larger PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1184 "1184 1184" _null_ _null_ _null_ _null_ timestamp_larger _null_ _null_ _null_ )); DESCR("larger of two"); + DATA(insert OID = 4051 ( timestamptz_smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1184 "1184 1184" _null_ _null_ _null_ _null_ timestamp_smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 4052 ( timestamptz_larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1184 "1184 1184" _null_ _null_ _null_ _null_ timestamp_larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); DATA(insert OID = 1197 ( interval_smaller PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1186 "1186 1186" _null_ _null_ _null_ _null_ interval_smaller _null_ _null_ _null_ )); DESCR("smaller of two"); DATA(insert OID = 1198 ( interval_larger PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1186 "1186 1186" _null_ _null_ _null_ _null_ interval_larger _null_ _null_ _null_ )); DESCR("larger of two"); + + DATA(insert OID = 4053 ( interval_smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1186 "1186 1186" _null_ _null_ _null_ _null_ interval_smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 4054 ( interval_larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1186 "1186 1186" _null_ _null_ _null_ _null_ interval_larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 1199 ( age PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1186 "1184 1184" _null_ _null_ _null_ _null_ timestamptz_age _null_ _null_ _null_ )); DESCR("date difference preserving months and years"); *************** DESCR("larger of two"); *** 1318,1323 **** --- 1367,1378 ---- DATA(insert OID = 1237 ( int8smaller PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 20 "20 20" _null_ _null_ _null_ _null_ int8smaller _null_ _null_ _null_ )); DESCR("smaller of two"); + DATA(insert OID = 4055 ( int8larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 20 "20 20" _null_ _null_ _null_ _null_ int8larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 4056 ( int8smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 20 "20 20" _null_ _null_ _null_ _null_ int8smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + + DATA(insert OID = 1238 ( texticregexeq PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "25 25" _null_ _null_ _null_ _null_ texticregexeq _null_ _null_ _null_ )); DATA(insert OID = 1239 ( texticregexne PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "25 25" _null_ _null_ _null_ _null_ texticregexne _null_ _null_ _null_ )); DATA(insert OID = 1240 ( nameicregexeq PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "19 25" _null_ _null_ _null_ _null_ nameicregexeq _null_ _null_ _null_ )); *************** DESCR("larger of two"); *** 1374,1379 **** --- 1429,1439 ---- DATA(insert OID = 2796 ( tidsmaller PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 27 "27 27" _null_ _null_ _null_ _null_ tidsmaller _null_ _null_ _null_ )); DESCR("smaller of two"); + DATA(insert OID = 4057 ( tidlarger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 27 "27 27" _null_ _null_ _null_ _null_ tidlarger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 4058 ( tidsmaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 27 "27 27" _null_ _null_ _null_ _null_ tidsmaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 1296 ( timedate_pl PGNSP PGUID 14 1 0 0 0 f f f f t f i 2 0 1114 "1083 1082" _null_ _null_ _null_ _null_ "select ($2 + $1)" _null_ _null_ _null_ )); DATA(insert OID = 1297 ( datetimetz_pl PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1184 "1082 1266" _null_ _null_ _null_ _null_ datetimetz_timestamptz _null_ _null_ _null_ )); DATA(insert OID = 1298 ( timetzdate_pl PGNSP PGUID 14 1 0 0 0 f f f f t f i 2 0 1184 "1266 1082" _null_ _null_ _null_ _null_ "select ($2 + $1)" _null_ _null_ _null_ )); *************** DESCR("larger of two"); *** 1515,1520 **** --- 1575,1590 ---- DATA(insert OID = 1380 ( timetz_smaller PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1266 "1266 1266" _null_ _null_ _null_ _null_ timetz_smaller _null_ _null_ _null_ )); DESCR("smaller of two"); + DATA(insert OID = 4059 ( time_larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1083 "1083 1083" _null_ _null_ _null_ _null_ time_larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 4060 ( time_smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1083 "1083 1083" _null_ _null_ _null_ _null_ time_smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 4061 ( timetz_larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1266 "1266 1266" _null_ _null_ _null_ _null_ timetz_larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 4062 ( timetz_smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1266 "1266 1266" _null_ _null_ _null_ _null_ timetz_smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + + DATA(insert OID = 1381 ( char_length PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 23 "25" _null_ _null_ _null_ _null_ textlen _null_ _null_ _null_ )); DESCR("character length"); *************** DATA(insert OID = 1766 ( numeric_smaller *** 2277,2282 **** --- 2347,2357 ---- DESCR("smaller of two"); DATA(insert OID = 1767 ( numeric_larger PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ numeric_larger _null_ _null_ _null_ )); DESCR("larger of two"); + DATA(insert OID = 4063 ( numeric_smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ numeric_smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 4064 ( numeric_larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ numeric_larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 1769 ( numeric_cmp PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "1700 1700" _null_ _null_ _null_ _null_ numeric_cmp _null_ _null_ _null_ )); DESCR("less-equal-greater"); DATA(insert OID = 1771 ( numeric_uminus PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 1700 "1700" _null_ _null_ _null_ _null_ numeric_uminus _null_ _null_ _null_ )); *************** DESCR("larger of two"); *** 2803,2808 **** --- 2878,2888 ---- DATA(insert OID = 1966 ( oidsmaller PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 26 "26 26" _null_ _null_ _null_ _null_ oidsmaller _null_ _null_ _null_ )); DESCR("smaller of two"); + DATA(insert OID = 4065 ( oidlarger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 26 "26 26" _null_ _null_ _null_ _null_ oidlarger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 4066 ( oidsmaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 26 "26 26" _null_ _null_ _null_ _null_ oidsmaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 1967 ( timestamptz PGNSP PGUID 12 1 0 0 timestamp_transform f f f f t f i 2 0 1184 "1184 23" _null_ _null_ _null_ _null_ timestamptz_scale _null_ _null_ _null_ )); DESCR("adjust timestamptz precision"); DATA(insert OID = 1968 ( time PGNSP PGUID 12 1 0 0 time_transform f f f f t f i 2 0 1083 "1083 23" _null_ _null_ _null_ _null_ time_scale _null_ _null_ _null_ )); *************** DATA(insert OID = 2035 ( timestamp_smal *** 2864,2869 **** --- 2944,2955 ---- DESCR("smaller of two"); DATA(insert OID = 2036 ( timestamp_larger PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1114 "1114 1114" _null_ _null_ _null_ _null_ timestamp_larger _null_ _null_ _null_ )); DESCR("larger of two"); + + DATA(insert OID = 4067 ( timestamp_smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1114 "1114 1114" _null_ _null_ _null_ _null_ timestamp_smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 4068 ( timestamp_larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1114 "1114 1114" _null_ _null_ _null_ _null_ timestamp_larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 2037 ( timezone PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 1266 "25 1266" _null_ _null_ _null_ _null_ timetz_zone _null_ _null_ _null_ )); DESCR("adjust time with time zone to new zone"); DATA(insert OID = 2038 ( timezone PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1266 "1186 1266" _null_ _null_ _null_ _null_ timetz_izone _null_ _null_ _null_ )); *************** DATA(insert OID = 3524 ( enum_smaller P *** 4254,4259 **** --- 4340,4350 ---- DESCR("smaller of two"); DATA(insert OID = 3525 ( enum_larger PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3500 "3500 3500" _null_ _null_ _null_ _null_ enum_larger _null_ _null_ _null_ )); DESCR("larger of two"); + DATA(insert OID = 4073 ( enum_smaller_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3500 "3500 3500" _null_ _null_ _null_ _null_ enum_smaller_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 4074 ( enum_larger_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3500 "3500 3500" _null_ _null_ _null_ _null_ enum_larger_inv _null_ _null_ _null_ )); + DESCR("inverse aggregate transition function"); + DATA(insert OID = 3526 ( max PGNSP PGUID 12 1 0 0 0 t f f f f f i 1 0 3500 "3500" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )); DESCR("maximum value of all enum input values"); DATA(insert OID = 3527 ( min PGNSP PGUID 12 1 0 0 0 t f f f f f i 1 0 3500 "3500" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )); diff --git a/src/include/utils/array.h b/src/include/utils/array.h index 9bbfaae..43e4973 100644 *** a/src/include/utils/array.h --- b/src/include/utils/array.h *************** extern Datum array_upper(PG_FUNCTION_ARG *** 206,212 **** --- 206,214 ---- extern Datum array_length(PG_FUNCTION_ARGS); extern Datum array_cardinality(PG_FUNCTION_ARGS); extern Datum array_larger(PG_FUNCTION_ARGS); + extern Datum array_larger_inv(PG_FUNCTION_ARGS); extern Datum array_smaller(PG_FUNCTION_ARGS); + extern Datum array_smaller_inv(PG_FUNCTION_ARGS); extern Datum generate_subscripts(PG_FUNCTION_ARGS); extern Datum generate_subscripts_nodir(PG_FUNCTION_ARGS); extern Datum array_fill(PG_FUNCTION_ARGS); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 031a43a..b869743 100644 *** a/src/include/utils/builtins.h --- b/src/include/utils/builtins.h *************** extern Datum enum_ge(PG_FUNCTION_ARGS); *** 167,173 **** --- 167,175 ---- extern Datum enum_gt(PG_FUNCTION_ARGS); extern Datum enum_cmp(PG_FUNCTION_ARGS); extern Datum enum_smaller(PG_FUNCTION_ARGS); + extern Datum enum_smaller_inv(PG_FUNCTION_ARGS); extern Datum enum_larger(PG_FUNCTION_ARGS); + extern Datum enum_larger_inv(PG_FUNCTION_ARGS); extern Datum enum_first(PG_FUNCTION_ARGS); extern Datum enum_last(PG_FUNCTION_ARGS); extern Datum enum_range_bounds(PG_FUNCTION_ARGS); *************** extern Datum int42div(PG_FUNCTION_ARGS); *** 241,249 **** --- 243,255 ---- extern Datum int4mod(PG_FUNCTION_ARGS); extern Datum int2mod(PG_FUNCTION_ARGS); extern Datum int2larger(PG_FUNCTION_ARGS); + extern Datum int2larger_inv(PG_FUNCTION_ARGS); extern Datum int2smaller(PG_FUNCTION_ARGS); + extern Datum int2smaller_inv(PG_FUNCTION_ARGS); extern Datum int4larger(PG_FUNCTION_ARGS); + extern Datum int4larger_inv(PG_FUNCTION_ARGS); extern Datum int4smaller(PG_FUNCTION_ARGS); + extern Datum int4smaller_inv(PG_FUNCTION_ARGS); extern Datum int4and(PG_FUNCTION_ARGS); extern Datum int4or(PG_FUNCTION_ARGS); *************** extern Datum float4abs(PG_FUNCTION_ARGS) *** 347,358 **** --- 353,368 ---- extern Datum float4um(PG_FUNCTION_ARGS); extern Datum float4up(PG_FUNCTION_ARGS); extern Datum float4larger(PG_FUNCTION_ARGS); + extern Datum float4larger_inv(PG_FUNCTION_ARGS); extern Datum float4smaller(PG_FUNCTION_ARGS); + extern Datum float4smaller_inv(PG_FUNCTION_ARGS); extern Datum float8abs(PG_FUNCTION_ARGS); extern Datum float8um(PG_FUNCTION_ARGS); extern Datum float8up(PG_FUNCTION_ARGS); extern Datum float8larger(PG_FUNCTION_ARGS); + extern Datum float8larger_inv(PG_FUNCTION_ARGS); extern Datum float8smaller(PG_FUNCTION_ARGS); + extern Datum float8smaller_inv(PG_FUNCTION_ARGS); extern Datum float4pl(PG_FUNCTION_ARGS); extern Datum float4mi(PG_FUNCTION_ARGS); extern Datum float4mul(PG_FUNCTION_ARGS); *************** extern Datum oidle(PG_FUNCTION_ARGS); *** 501,507 **** --- 511,519 ---- extern Datum oidge(PG_FUNCTION_ARGS); extern Datum oidgt(PG_FUNCTION_ARGS); extern Datum oidlarger(PG_FUNCTION_ARGS); + extern Datum oidlarger_inv(PG_FUNCTION_ARGS); extern Datum oidsmaller(PG_FUNCTION_ARGS); + extern Datum oidsmaller_inv(PG_FUNCTION_ARGS); extern Datum oidvectorin(PG_FUNCTION_ARGS); extern Datum oidvectorout(PG_FUNCTION_ARGS); extern Datum oidvectorrecv(PG_FUNCTION_ARGS); *************** extern Datum tidgt(PG_FUNCTION_ARGS); *** 707,713 **** --- 719,727 ---- extern Datum tidge(PG_FUNCTION_ARGS); extern Datum bttidcmp(PG_FUNCTION_ARGS); extern Datum tidlarger(PG_FUNCTION_ARGS); + extern Datum tidlarger_inv(PG_FUNCTION_ARGS); extern Datum tidsmaller(PG_FUNCTION_ARGS); + extern Datum tidsmaller_inv(PG_FUNCTION_ARGS); extern Datum currtid_byreloid(PG_FUNCTION_ARGS); extern Datum currtid_byrelname(PG_FUNCTION_ARGS); *************** extern Datum bpchargt(PG_FUNCTION_ARGS); *** 730,736 **** --- 744,752 ---- extern Datum bpcharge(PG_FUNCTION_ARGS); extern Datum bpcharcmp(PG_FUNCTION_ARGS); extern Datum bpchar_larger(PG_FUNCTION_ARGS); + extern Datum bpchar_larger_inv(PG_FUNCTION_ARGS); extern Datum bpchar_smaller(PG_FUNCTION_ARGS); + extern Datum bpchar_smaller_inv(PG_FUNCTION_ARGS); extern Datum bpcharlen(PG_FUNCTION_ARGS); extern Datum bpcharoctetlen(PG_FUNCTION_ARGS); extern Datum hashbpchar(PG_FUNCTION_ARGS); *************** extern Datum text_le(PG_FUNCTION_ARGS); *** 770,776 **** --- 786,794 ---- extern Datum text_gt(PG_FUNCTION_ARGS); extern Datum text_ge(PG_FUNCTION_ARGS); extern Datum text_larger(PG_FUNCTION_ARGS); + extern Datum text_larger_inv(PG_FUNCTION_ARGS); extern Datum text_smaller(PG_FUNCTION_ARGS); + extern Datum text_smaller_inv(PG_FUNCTION_ARGS); extern Datum text_pattern_lt(PG_FUNCTION_ARGS); extern Datum text_pattern_le(PG_FUNCTION_ARGS); extern Datum text_pattern_gt(PG_FUNCTION_ARGS); *************** extern Datum numeric_div_trunc(PG_FUNCTI *** 980,986 **** --- 998,1006 ---- extern Datum numeric_mod(PG_FUNCTION_ARGS); extern Datum numeric_inc(PG_FUNCTION_ARGS); extern Datum numeric_smaller(PG_FUNCTION_ARGS); + extern Datum numeric_smaller_inv(PG_FUNCTION_ARGS); extern Datum numeric_larger(PG_FUNCTION_ARGS); + extern Datum numeric_larger_inv(PG_FUNCTION_ARGS); extern Datum numeric_fac(PG_FUNCTION_ARGS); extern Datum numeric_sqrt(PG_FUNCTION_ARGS); extern Datum numeric_exp(PG_FUNCTION_ARGS); diff --git a/src/include/utils/cash.h b/src/include/utils/cash.h index 3a491f9..4e184cc 100644 *** a/src/include/utils/cash.h --- b/src/include/utils/cash.h *************** extern Datum int2_mul_cash(PG_FUNCTION_A *** 60,66 **** --- 60,68 ---- extern Datum cash_div_int2(PG_FUNCTION_ARGS); extern Datum cashlarger(PG_FUNCTION_ARGS); + extern Datum cashlarger_inv(PG_FUNCTION_ARGS); extern Datum cashsmaller(PG_FUNCTION_ARGS); + extern Datum cashsmaller_inv(PG_FUNCTION_ARGS); extern Datum cash_words(PG_FUNCTION_ARGS); diff --git a/src/include/utils/date.h b/src/include/utils/date.h index 622aa19..9f459ac 100644 *** a/src/include/utils/date.h --- b/src/include/utils/date.h *************** extern Datum date_cmp(PG_FUNCTION_ARGS); *** 108,114 **** --- 108,116 ---- extern Datum date_sortsupport(PG_FUNCTION_ARGS); extern Datum date_finite(PG_FUNCTION_ARGS); extern Datum date_larger(PG_FUNCTION_ARGS); + extern Datum date_larger_inv(PG_FUNCTION_ARGS); extern Datum date_smaller(PG_FUNCTION_ARGS); + extern Datum date_smaller_inv(PG_FUNCTION_ARGS); extern Datum date_mi(PG_FUNCTION_ARGS); extern Datum date_pli(PG_FUNCTION_ARGS); extern Datum date_mii(PG_FUNCTION_ARGS); *************** extern Datum time_cmp(PG_FUNCTION_ARGS); *** 168,174 **** --- 170,178 ---- extern Datum time_hash(PG_FUNCTION_ARGS); extern Datum overlaps_time(PG_FUNCTION_ARGS); extern Datum time_larger(PG_FUNCTION_ARGS); + extern Datum time_larger_inv(PG_FUNCTION_ARGS); extern Datum time_smaller(PG_FUNCTION_ARGS); + extern Datum time_smaller_inv(PG_FUNCTION_ARGS); extern Datum time_mi_time(PG_FUNCTION_ARGS); extern Datum timestamp_time(PG_FUNCTION_ARGS); extern Datum timestamptz_time(PG_FUNCTION_ARGS); *************** extern Datum timetz_cmp(PG_FUNCTION_ARGS *** 195,201 **** --- 199,207 ---- extern Datum timetz_hash(PG_FUNCTION_ARGS); extern Datum overlaps_timetz(PG_FUNCTION_ARGS); extern Datum timetz_larger(PG_FUNCTION_ARGS); + extern Datum timetz_larger_inv(PG_FUNCTION_ARGS); extern Datum timetz_smaller(PG_FUNCTION_ARGS); + extern Datum timetz_smaller_inv(PG_FUNCTION_ARGS); extern Datum timetz_time(PG_FUNCTION_ARGS); extern Datum time_timetz(PG_FUNCTION_ARGS); extern Datum timestamptz_timetz(PG_FUNCTION_ARGS); diff --git a/src/include/utils/int8.h b/src/include/utils/int8.h index d63e3a9..d102ccb 100644 *** a/src/include/utils/int8.h --- b/src/include/utils/int8.h *************** extern Datum int8inc(PG_FUNCTION_ARGS); *** 77,83 **** --- 77,85 ---- extern Datum int8inc_any(PG_FUNCTION_ARGS); extern Datum int8inc_float8_float8(PG_FUNCTION_ARGS); extern Datum int8larger(PG_FUNCTION_ARGS); + extern Datum int8larger_inv(PG_FUNCTION_ARGS); extern Datum int8smaller(PG_FUNCTION_ARGS); + extern Datum int8smaller_inv(PG_FUNCTION_ARGS); extern Datum int8and(PG_FUNCTION_ARGS); extern Datum int8or(PG_FUNCTION_ARGS); diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h index 2731c6a..4f6673c 100644 *** a/src/include/utils/timestamp.h --- b/src/include/utils/timestamp.h *************** extern Datum timestamp_cmp(PG_FUNCTION_A *** 111,117 **** --- 111,119 ---- extern Datum timestamp_sortsupport(PG_FUNCTION_ARGS); extern Datum timestamp_hash(PG_FUNCTION_ARGS); extern Datum timestamp_smaller(PG_FUNCTION_ARGS); + extern Datum timestamp_smaller_inv(PG_FUNCTION_ARGS); extern Datum timestamp_larger(PG_FUNCTION_ARGS); + extern Datum timestamp_larger_inv(PG_FUNCTION_ARGS); extern Datum timestamp_eq_timestamptz(PG_FUNCTION_ARGS); extern Datum timestamp_ne_timestamptz(PG_FUNCTION_ARGS); *************** extern Datum interval_finite(PG_FUNCTION *** 151,157 **** --- 153,161 ---- extern Datum interval_cmp(PG_FUNCTION_ARGS); extern Datum interval_hash(PG_FUNCTION_ARGS); extern Datum interval_smaller(PG_FUNCTION_ARGS); + extern Datum interval_smaller_inv(PG_FUNCTION_ARGS); extern Datum interval_larger(PG_FUNCTION_ARGS); + extern Datum interval_larger_inv(PG_FUNCTION_ARGS); extern Datum interval_justify_interval(PG_FUNCTION_ARGS); extern Datum interval_justify_hours(PG_FUNCTION_ARGS); extern Datum interval_justify_days(PG_FUNCTION_ARGS); diff --git a/src/test/regress/expected/window.out b/src/test/regress/expected/window.out index e3eba47..3c4ad7f 100644 *** a/src/test/regress/expected/window.out --- b/src/test/regress/expected/window.out *************** DROP FUNCTION logging_sfunc_nonstrict(te *** 1305,1310 **** --- 1305,1403 ---- -- Test the MIN and MAX inverse transition functions -- -- + SELECT v,MAX(v) OVER w,MIN(v) OVER w + FROM (VALUES(1,10),(2,20),(3,30),(4,40)) v(i,v) + WINDOW w AS (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING); + v | max | min + ----+-----+----- + 10 | 20 | 10 + 20 | 30 | 20 + 30 | 40 | 30 + 40 | 40 | 40 + (4 rows) + + SELECT v,MAX(v) OVER w,MIN(v) OVER w + FROM (VALUES(1,10::int),(2,20),(3,NULL),(4,40)) v(i,v) + WINDOW w AS (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING); + v | max | min + ----+-----+----- + 10 | 20 | 10 + 20 | 20 | 20 + | 40 | 40 + 40 | 40 | 40 + (4 rows) + + SELECT v,MAX(v) FILTER(WHERE v <> 40) OVER w,MIN(v) OVER w + FROM (VALUES(1,10::int),(2,20),(3,30),(4,40)) v(i,v) + WINDOW w AS (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING); + v | max | min + ----+-----+----- + 10 | 20 | 10 + 20 | 30 | 20 + 30 | 30 | 30 + 40 | | 40 + (4 rows) + + SELECT v,MAX(v) OVER w,MIN(v) OVER w + FROM (VALUES(1,40::int),(2,40),(3,20),(4,NULL),(5,10)) v(i,v) + WINDOW w AS (ORDER BY i RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING); + v | max | min + ----+-----+----- + 40 | 40 | 10 + 40 | 40 | 10 + 20 | 20 | 10 + | 10 | 10 + 10 | 10 | 10 + (5 rows) + + SELECT v,MAX(CASE WHEN v <= 20 THEN NULL ELSE v END) OVER w,MIN(v) OVER w + FROM (VALUES(1,40::int),(2,40),(3,20),(4,NULL),(5,10)) v(i,v) + WINDOW w AS (ORDER BY i RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING); + v | max | min + ----+-----+----- + 40 | 40 | 10 + 40 | 40 | 10 + 20 | | 10 + | | 10 + 10 | | 10 + (5 rows) + + SELECT v,MAX(v) OVER w,MIN(v) OVER w + FROM (VALUES(1,'ad'),(2,'ab'),(3,'ad'),(4,'aa'),(5,'ae')) v(i,v) + WINDOW w AS (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING); + v | max | min + ----+-----+----- + ad | ad | ab + ab | ad | ab + ad | ad | aa + aa | ae | aa + ae | ae | ae + (5 rows) + + SELECT v,MAX(v) OVER w,MIN(v) OVER w + FROM (VALUES(1,'ad'),(2,'ab'),(3,'ad'),(4,'aa'),(5,'ae')) v(i,v) + WINDOW w AS (ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING); + v | max | min + ----+-----+----- + ad | ad | ab + ab | ad | ab + ad | ad | aa + aa | ae | aa + ae | ae | ae + (5 rows) + + SELECT v,p,MAX(v) OVER w,MIN(v) OVER w + FROM (VALUES(1,100,'ad'),(2,100,'ab'),(3,200,'ad'),(4,200,'aa'),(5,100,'ae')) v(i,p,v) + WINDOW w AS (PARTITION BY p ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING); + v | p | max | min + ----+-----+-----+----- + ad | 100 | ae | ab + ab | 100 | ae | ab + ae | 100 | ae | ae + ad | 200 | ad | aa + aa | 200 | aa | aa + (5 rows) + -- -- -- Tests of the collecting inverse transition functions diff --git a/src/test/regress/sql/window.sql b/src/test/regress/sql/window.sql index bd8dbdc..bde2a49 100644 *** a/src/test/regress/sql/window.sql --- b/src/test/regress/sql/window.sql *************** DROP FUNCTION logging_sfunc_nonstrict(te *** 488,493 **** --- 488,525 ---- -- -- + SELECT v,MAX(v) OVER w,MIN(v) OVER w + FROM (VALUES(1,10),(2,20),(3,30),(4,40)) v(i,v) + WINDOW w AS (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING); + + SELECT v,MAX(v) OVER w,MIN(v) OVER w + FROM (VALUES(1,10::int),(2,20),(3,NULL),(4,40)) v(i,v) + WINDOW w AS (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING); + + SELECT v,MAX(v) FILTER(WHERE v <> 40) OVER w,MIN(v) OVER w + FROM (VALUES(1,10::int),(2,20),(3,30),(4,40)) v(i,v) + WINDOW w AS (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING); + + SELECT v,MAX(v) OVER w,MIN(v) OVER w + FROM (VALUES(1,40::int),(2,40),(3,20),(4,NULL),(5,10)) v(i,v) + WINDOW w AS (ORDER BY i RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING); + + SELECT v,MAX(CASE WHEN v <= 20 THEN NULL ELSE v END) OVER w,MIN(v) OVER w + FROM (VALUES(1,40::int),(2,40),(3,20),(4,NULL),(5,10)) v(i,v) + WINDOW w AS (ORDER BY i RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING); + + SELECT v,MAX(v) OVER w,MIN(v) OVER w + FROM (VALUES(1,'ad'),(2,'ab'),(3,'ad'),(4,'aa'),(5,'ae')) v(i,v) + WINDOW w AS (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING); + + SELECT v,MAX(v) OVER w,MIN(v) OVER w + FROM (VALUES(1,'ad'),(2,'ab'),(3,'ad'),(4,'aa'),(5,'ae')) v(i,v) + WINDOW w AS (ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING); + + SELECT v,p,MAX(v) OVER w,MIN(v) OVER w + FROM (VALUES(1,100,'ad'),(2,100,'ab'),(3,200,'ad'),(4,200,'aa'),(5,100,'ae')) v(i,p,v) + WINDOW w AS (PARTITION BY p ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING); + -- -- -- Tests of the collecting inverse transition functions