Postgresql自定义c聚合函数抛出分段错误

时间:2017-02-07 15:54:20

标签: 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_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);
        }
    }

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

1 个答案:

答案 0 :(得分:0)

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

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