Postgresql自定义c聚合函数引发分段错误

Postgresql自定义c聚合函数引发分段错误,c,postgresql,C,Postgresql,我试图创建一个聚合函数,它返回具有最小/最大时间戳的行中的列的值。下面的代码对一些较大的输入抛出了分段错误 PG_FUNCTION_INFO_V1(minmax); Datum minmax(PG_FUNCTION_ARGS) { if(PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3)) { if(PG_ARGISNULL(0)) { PG_RETU

我试图创建一个聚合函数,它返回具有最小/最大时间戳的行中的列的值。下面的代码对一些较大的输入抛出了分段错误

    PG_FUNCTION_INFO_V1(minmax);

    Datum minmax(PG_FUNCTION_ARGS) {
        if(PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3)) {
            if(PG_ARGISNULL(0)) {
                PG_RETURN_NULL();
            }
            else {
                PG_RETURN_HEAPTUPLEHEADER(PG_GETARG_HEAPTUPLEHEADER(0));
            }
        }

        Timestamp epoch = PG_GETARG_TIMESTAMP(1);
        Datum col = PG_GETARG_DATUM(2);
        Oid element_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
        bool is_min = PG_GETARG_BOOL(3);

        Timestamp minmax_epoch = is_min ? LONG_MAX : LONG_MIN;
        Datum minmax_col;
        if(PG_ARGISNULL(0)) {
            // first call
            minmax_epoch = epoch;
            minmax_col = col;
        }
        else {
            // state
            HeapTupleHeader hth_state = PG_GETARG_HEAPTUPLEHEADER(0);

            bool isnull_state_minmax_timestamp;
            Datum d_state_minmax_timestamp = GetAttributeByNum(hth_state, (AttrNumber) 1, &isnull_state_minmax_timestamp);

            minmax_epoch = DatumGetInt64(d_state_minmax_timestamp);
            if((is_min && epoch < minmax_epoch) || (!is_min && epoch > minmax_epoch)) {
                minmax_epoch = epoch;
                minmax_col = col;
            }
            else {
                PG_RETURN_HEAPTUPLEHEADER(hth_state);
            }
        }
        // return state
        TupleDesc   tupdesc;
        Datum       values[2];
        bool        nulls[2];
        MemSet(values, 0, sizeof(values));
        MemSet(nulls, 0, sizeof(nulls));

        tupdesc = CreateTemplateTupleDesc(2, false);
        TupleDescInitEntry(tupdesc, (AttrNumber) 1, "minmax_timestamp", INT8OID, -1, 0);
        TupleDescInitEntry(tupdesc, (AttrNumber) 2, "minmax_col", element_type, -1, 0);

        tupdesc = BlessTupleDesc(tupdesc);
        values[0] = Int64GetDatum(minmax_epoch);
        values[1] = minmax_col;

        HeapTuple rettuple = heap_form_tuple(tupdesc, values, nulls);
        PG_RETURN_DATUM(HeapTupleGetDatum(rettuple));
    }

    PG_FUNCTION_INFO_V1(get_minmax);

    Datum get_minmax(PG_FUNCTION_ARGS) {
        if(PG_ARGISNULL(0)) {
            PG_RETURN_NULL();
        }
        else {
            // state
            //error here
            HeapTupleHeader hth_state = PG_GETARG_HEAPTUPLEHEADER(0);

            bool isnull_state_minmax_col;
            Datum d_state_minmax_col = GetAttributeByNum(hth_state, (AttrNumber) 2, &isnull_state_minmax_col);

            PG_RETURN_DATUM(d_state_minmax_col);
        }
    }
PG_函数_信息_V1(最小值);
基准最小值最大值(PG_函数参数){
if(PG|u ARGISNULL(1)| PG|u ARGISNULL(2)| PG|u ARGISNULL(3)){
if(PG_ARGISNULL(0)){
PG_RETURN_NULL();
}
否则{
PG_RETURN_HEAPTUPLEHEADER(PG_GETARG_HEAPTUPLEHEADER(0));
}
}
Timestamp epoch=PG_GETARG_时间戳(1);
基准col=PG_GETARG_基准(2);
Oid元素类型=get\u fn\u expr\u argtype(fcinfo->flinfo,2);
bool is_min=PG_GETARG_bool(3);
时间戳minmax\u epoch=is\u min?LONG\u MAX:LONG\u min;
基准最小最大值;
if(PG_ARGISNULL(0)){
//第一个电话
minmax_epoch=epoch;
minmax_col=col;
}
否则{
//陈述
HeapTupleHeader hth_state=PG_GETARG_HeapTupleHeader(0);
bool isnull\u state\u minmax\u timestamp;
数据d_state_minmax_timestamp=GetAttributeByNum(hth_state,(AttrNumber)1,&isnull_state_minmax_timestamp);
minmax_epoch=DatumGetInt64(d_state_minmax_timestamp);
if((is_min&&epochminmax_epoch)){
minmax_epoch=epoch;
minmax_col=col;
}
否则{
PG_返回_堆头(hth_状态);
}
}
//返回状态
TupleDesc tupdesc;
基准值[2];
布尔空值[2];
MemSet(值,0,sizeof(值));
MemSet(nulls,0,sizeof(nulls));
tupdesc=CreateTemplateTupleDesc(2,false);
TupleDescInitEntry(tupdesc,(AttrNumber)1,“minmax_时间戳”,INT8OID,-1,0);
TupleDescInitEntry(tupdesc,(AttrNumber)2,“minmax\u col”,元素类型,-1,0);
tupdesc=BlessTupleDesc(tupdesc);
值[0]=Int64GetDatum(最小-最大历元);
值[1]=最小最大值;
HeapTuple rettuple=heap\u form\u tuple(tupdesc,value,null);
PG_RETURN_DATUM(HeapTupleGetDatum(rettuple));
}
PG函数信息V1(获取最小值);
数据获取最小值(PG函数参数){
if(PG_ARGISNULL(0)){
PG_RETURN_NULL();
}
否则{
//陈述
//这里出错
HeapTupleHeader hth_state=PG_GETARG_HeapTupleHeader(0);
布尔值为空,状态为最小最大值;
数据d_state_minmax_col=GetAttributeByNum(hth_state,(AttrNumber)2,&isnull_state_minmax_col);
PG_返回_数据(d_状态_最小最大值_列);
}
}

seg错误似乎出现在函数get_minmax获取PG_GETARG_HEAPTUPLEHEADER参数的过程中。可能是我没有在minmax函数中正确构建它。

上述代码似乎没有任何问题。我在greenplum中使用聚合函数,而不是postgresql。对于那些在greenplum中编写聚合函数并实现PREFUNC的人,请确保检查两个参数是否都为NULL并相应地进行处理


专家确实建议,是否可以在内存使用等方面对上述功能进行任何改进

您应该研究一下。或者学习如何。这个问题可能与函数注册和转换类型注册有关。为此,元组的速度很慢-最好使用自己的内部类型-内部具有两个时间戳的C结构-时间戳在Postgres中是固定的数据类型。