2017-08-04 4 views
1

PostgreSQL 9.6のドキュメントに基づいて、レコードセットを返す関数を実行しようとしています。 C言語のコードに従う:Cでレコードセットを返す

#include <funcapi.h> 
..... 

FuncCallContext *funcctx; /*help control to save and remember state */ 
    MemoryContext oldcontext, newcontext; 
    Datum result; 
    uint32 ct_call; 
    TupleDesc tupdesc; 
    AttInMetadata *attinmeta; 

    // struct line_reverse_tuple_args *args; /*aux struct for save state*/ 

    // struct geo_linestring *line1; 
    // struct geo_linestring *line2; 

    elog(NOTICE, "is being called called"); 

    /* Determine if the function is being called for the first time.*/ 
    if(SRF_IS_FIRSTCALL()) 
    { 
    elog(NOTICE, "geo_linestring_intersection_points_v1 first called"); 

    /* initialize the FuncCallContext */ 
    funcctx = SRF_FIRSTCALL_INIT(); 

    /* switch to memory context appropriate for multiple function calls */ 
    newcontext = funcctx->multi_call_memory_ctx; 
     oldcontext = MemoryContextSwitchTo(newcontext); 

    // line1 = PG_GETARG_GEOLINESTRING_TYPE_P(0); 
    // line2 = PG_GETARG_GEOLINESTRING_TYPE_P(1); 

    /* allocate and zero-fill struct for persisting extracted arguments*/ 
    //args = palloc0(sizeof(struct line_reverse_tuple_args)); 

    //funcctx->user_fctx = args; 

    /* total number of tuples to be returned */ 
    funcctx->max_calls = 3; 

     /* Build a tuple descriptor for our result type */ 
    if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) 
     ereport(ERROR, 
       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 
       errmsg("function returning record called in context " 
         "that cannot accept type record"))); 



    attinmeta = TupleDescGetAttInMetadata(tupdesc); 
    funcctx->attinmeta = attinmeta; 


    /* restore memory context */ 
    MemoryContextSwitchTo(oldcontext); 

    elog(NOTICE, "geo_linestring_intersection_points_v1 end first call"); 

    } 

    funcctx = SRF_PERCALL_SETUP(); 


    ct_call = funcctx->call_cntr; 
    attinmeta = funcctx->attinmeta; 

    elog(NOTICE, "funcapi others call"); 

    if (ct_call < funcctx->max_calls) 
    { 
    HeapTuple tuple; 
    char  **values; 

    /* 
    * Prepare a values array for building the returned tuple. 
    * This should be an array of C strings which will 
    * be processed later by the type input functions. 
    */ 
    values = (char **) palloc(3 * sizeof(char *)); 
    values[0] = (char *) palloc(16 * sizeof(char)); 
    values[1] = (char *) palloc(16 * sizeof(char)); 
    values[2] = (char *) palloc(16 * sizeof(char)); 

    snprintf(values[0], 16, "%d", 1 * PG_GETARG_INT32(1)); 
    snprintf(values[1], 16, "%d", 2 * PG_GETARG_INT32(1)); 
    snprintf(values[2], 16, "%d", 3 * PG_GETARG_INT32(1)); 

    /* build a tuple */ 
    tuple = BuildTupleFromCStrings(attinmeta, values); 

    /* make the tuple into a datum */ 
    result = HeapTupleGetDatum(tuple); 

    /* clean up (this is not really necessary) */ 
    pfree(values[0]); 
    pfree(values[1]); 
    pfree(values[2]); 
    pfree(values); 

    SRF_RETURN_NEXT(funcctx, result); 
    } 

    else 
    { 
    SRF_RETURN_DONE(funcctx); 
    } 

sqlでの関数の作成は、ドキュメントでは同じです。 しかし、私はこのようなSQLを実行する場合:

SELECT * FROM build_rows_funcapi(1,48); 

サーバーがクラッシュします。次のメッセージが表示されます。

サーバーが予期せず接続を閉じました。 ELOGに基づいて

、あれば関数が最初にまで実行されていることを観察することができる:もし(SRF_IS_FIRSTCALL())

私は間違って何かを実装する、または何かを忘れているだろうか?

+0

よくある問題は、返されたデータに間違ったメモリコンテキストを使用しています。 –

+0

スタックトレースを取得しようとすると(https://wiki.postgresql.org/wiki/Generating_a_stack_trace_of_a_PostgreSQL_backend)、何がうまくいかなかったのか、どこに問題があるのか​​を理解するのに役立ちます。 –

+0

完全なCファイルを投稿してください。 –

答えて

0

サーバと同じpostgre SQLバージョンを使用していることを確認してください。そうでない場合は、正しいバージョンをダウンロードしてください。これが問題でない場合は、pg_hba.confファイルのIP設定が正しく設定されているかどうかを確認してください。

+0

サーバとPostgreSQLのバージョンは同じです:9.6。また、pg_hba.confのIPが正しく設定されています。ありがとうございますが、問題はまだ続きます。 'SRF_IS_FIRSTCALL()'関数はサーバをクラッシュさせています。 –

関連する問題