Fwd: SPI_palloc problem

From: Aron Widforss <pgsql-general(at)antarkt(dot)is>
To: pgsql-general(at)postgresql(dot)org
Subject: Fwd: SPI_palloc problem
Date: 2017-10-29 18:40:24
Message-ID: 1509302424.3447951.1154724368.6B4BC75A@webmail.messagingengine.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

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(at)antarkt(dot)is>
To: pgsql-general(at)postgresql(dot)org
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"));
}

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Ron Johnson 2017-10-29 18:45:04 Old pg_clog files
Previous Message Karsten Hilbert 2017-10-28 10:58:11 Re: Where to find development builds of pg for windows