Search Postgresql Archives

Fwd: SPI_palloc problem

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I mailed this from my main email address instead of the one I'm
subscribed to pgsql-general with. So, here goes.

----- Original message -----
From: Aron Widforss <aron@xxxxxxxxxx>
To: pgsql-general@xxxxxxxxxxxxxx
Subject: SPI_palloc problem
Date: Sun, 29 Oct 2017 19:35:30 +0100

Good evening,

I'm really new to PostgreSQL, and even C, but am trying to put together
a small pathfinding module to learn about it. Right now I'm just writing
a function to load my graph into a convenient data structure to use
later. I'm currently just loading the data of each vertice into my data
structure and then printing the loaded position out with elog(). It
works, but when I try to use SPI_palloc instead of palloc it disconnects
every time.

I suspect that my bug is really trivial, so maybe someone on this list
can just see what it is in the code and save me some time. :)

Regards,
Aron Widforss

Here is my version, example data and program:

pathfinding-hike=# SELECT version();
                                                     version             
-----------------------------------------------------------------------------------------------------------------
 PostgreSQL 9.5.9 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu
 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609, 64-bit
(1 row)

----

pathfinding-hike=# SELECT * FROM toc LIMIT 10;
 node |       pos        | connected  |    length     |     costs     | 
  lines    
------+------------------+------------+---------------+---------------+------------
    1 | {268582,6528365} | {2}        | {297}         | {297}         |
    {1}
    2 | {268773,6528472} | {1}        | {297}         | {297}         |
    {1}
    3 | {269103,6534918} | {15}       | {676}         | {676}         |
    {2}
    4 | {269436,6534931} | {12}       | {263}         | {263}         |
    {4}
    5 | {269521,6534450} | {11}       | {373}         | {373}         |
    {6}
    6 | {269535,6536629} | {28,22,7}  | {894,1508,66} | {894,1508,66} |
    {7,3,8}
    7 | {269542,6536693} | {6,9,9}    | {66,657,218}  | {66,657,218}  |
    {8,5,9}
    8 | {269585,6535610} | {14}       | {70}          | {70}          |
    {10}
    9 | {269631,6536886} | {7,7,36}   | {657,218,584} | {657,218,584} |
    {5,9,11}
   10 | {269642,6534754} | {12,20,11} | {137,140,6}   | {137,140,6}   |
   {12,13,14}
(10 rows)

----

#include "postgres.h"
#include "utils/array.h"
#include "utils/lsyscache.h"
#include "catalog/pg_type.h"
#include "executor/spi.h"
#include "utils/builtins.h"

int check_err(int code);
int check_err(int code)
{
    if(code < 0) {
        elog(ERROR, "%m");
    }
    return code;
}

int32_t * get_int_arr(HeapTuple tuple, TupleDesc rowdesc, int fnumber);
int32_t * get_int_arr(HeapTuple tuple, TupleDesc rowdesc, int fnumber)
{
    Datum     raw_arr;
    ArrayType *pg_arr;
    Datum     *c_arr;
    bool      isnull;
    /* Parameters for data alignment */
    Oid       eltype;
    int16     typlen;
    bool      typbyval;
    char      typalign;
    /* Info about unwrapped array */
    int32_t   *int_arr;
    int       arr_len;
    int       arr_dim;

    /* Get array raw-format */
    raw_arr = SPI_getbinval(tuple, rowdesc, fnumber, &isnull);
    check_err(SPI_result);
    if(isnull) {
        elog(ERROR, "Cannot deconstruct null array");
    }

    /* Get array db-format */
    pg_arr  = DatumGetArrayTypeP(raw_arr);
    arr_dim = ARR_NDIM(pg_arr);
    eltype  = ARR_ELEMTYPE(pg_arr);
    //TODO: More thorough type checking has to be done in plpgsql
    if(eltype != INT4OID) {
        elog(ERROR, "Array not of type Integer");
    }

    /* Get array as C-array (length prepended to 1st element) */
    get_typlenbyvalalign(eltype, &typlen, &typbyval, &typalign);
    if(arr_dim != 1) {
        elog(ERROR, "Cannot interpret multidimensional arrays");
    }
    deconstruct_array(pg_arr, eltype, typlen, typbyval, typalign,
                      &c_arr, NULL, &arr_len);
    int_arr = palloc((arr_len+1)*sizeof(int32_t));
    for(int i = 0; i<arr_len; i++) {
        int_arr[i+1] = DatumGetInt32(c_arr[i]);
    }
    int_arr[0] = arr_len+1;

    return int_arr;
}
    
uint32_t * get_uint_arr(HeapTuple tuple, TupleDesc rowdesc, int
fnumber);
uint32_t * get_uint_arr(HeapTuple tuple, TupleDesc rowdesc, int fnumber)
{
    int32_t  *int_arr;
    int_arr = get_int_arr(tuple, rowdesc, fnumber);

    for(int i = 1; i < int_arr[0]; i++) {
        if(int_arr[i] < 0) {
            elog(ERROR, "Unsigned int stored as negative in database");
        }
    }

    return (uint32_t *)int_arr;
}
                 
PG_MODULE_MAGIC;

PG_FUNCTION_INFO_V1(astarc);
Datum
astarc(PG_FUNCTION_ARGS)
{
    int rows;

    typedef struct node node;
    struct node {
        int32_t *pos;
        uint32_t *conn;
        uint32_t *costs;
        uint32_t *edges;
    };

    struct node *graph;

    check_err(SPI_connect());
    check_err(SPI_execute("SELECT * FROM toc", true, 10));
    rows = SPI_processed;

    graph = palloc((rows + 1)*sizeof(node));
    // Store size of array in first connected[]
    graph[0].conn[0] = rows+1;

    if(rows > 0 && SPI_tuptable != NULL) {
        TupleDesc tupdesc = SPI_tuptable->tupdesc;
        SPITupleTable *tuptable = SPI_tuptable;

        for (uint32_t i = 0; i < rows; i++) {
            HeapTuple tuple = tuptable->vals[i];
            graph[i].pos   = get_int_arr(tuple, tupdesc, 2);
            graph[i].conn  = get_uint_arr(tuple, tupdesc, 3);
            graph[i].costs = get_uint_arr(tuple, tupdesc, 5);
            graph[i].edges = get_uint_arr(tuple, tupdesc, 6);

            elog(INFO, "x: %i, y: %i", graph[i].pos[1],
            graph[i].pos[2]);
        }
    }

    if(rows == 0) {
        elog(ERROR, "Graph not found");
    }

    check_err(SPI_finish());

    PG_RETURN_TEXT_P(cstring_to_text("test"));
}


-- 
Sent via pgsql-general mailing list (pgsql-general@xxxxxxxxxxxxxx)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Postgresql Jobs]     [Postgresql Admin]     [Postgresql Performance]     [Linux Clusters]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Postgresql & PHP]     [Yosemite]

  Powered by Linux