PGROUTING  2.6-dev
trsp.c File Reference
#include "c_common/postgres_connection.h"
#include "catalog/pg_type.h"
#include "c_common/debug_macro.h"
#include "c_types/trsp/trsp.h"
Include dependency graph for trsp.c:

Go to the source code of this file.

Classes

struct  edge_columns
 
struct  restrict_columns
 

Typedefs

typedef struct edge_columns edge_columns_t
 
typedef struct restrict_columns restrict_columns_t
 

Functions

static int compute_trsp (char *sql, int dovertex, int64_t start_id, double start_pos, int64_t end_id, double end_pos, bool directed, bool has_reverse_cost, char *restrict_sql, path_element_tt **path, size_t *path_count)
 
static void fetch_edge (HeapTuple *tuple, TupleDesc *tupdesc, edge_columns_t *edge_columns, edge_t *target_edge)
 
static int fetch_edge_columns (SPITupleTable *tuptable, edge_columns_t *edge_columns, bool has_reverse_cost)
 
static void fetch_restrict (HeapTuple *tuple, TupleDesc *tupdesc, restrict_columns_t *restrict_columns, restrict_t *rest)
 
static int fetch_restrict_columns (SPITupleTable *tuptable, restrict_columns_t *restrict_columns)
 
static int finish (int code, int ret)
 
 PG_FUNCTION_INFO_V1 (turn_restrict_shortest_path_edge)
 
PGDLLEXPORT Datum turn_restrict_shortest_path_edge (PG_FUNCTION_ARGS)
 

Typedef Documentation

typedef struct edge_columns edge_columns_t

Function Documentation

static int compute_trsp ( char *  sql,
int  dovertex,
int64_t  start_id,
double  start_pos,
int64_t  end_id,
double  end_pos,
bool  directed,
bool  has_reverse_cost,
char *  restrict_sql,
path_element_tt **  path,
size_t *  path_count 
)
static

hack always returns 0 -1 when installed on EDB VC++ 64-bit without this

Definition at line 288 of file trsp.c.

References path_element::cost, edge_t::cost, path_element::edge_id, fetch_edge(), fetch_edge_columns(), fetch_restrict(), fetch_restrict_columns(), finish(), edge_columns::id, if(), PG_FUNCTION_INFO_V1(), PGR_DBG, edge_t::source, edge_columns::source, edge_t::target, edge_columns::target, restrict_columns::target_id, trsp_edge_wrapper(), trsp_node_wrapper(), TUPLIMIT, turn_restrict_shortest_path_edge(), and path_element::vertex_id.

Referenced by turn_restrict_shortest_path_edge().

299  {
300 
301  int SPIcode;
302  SPIPlanPtr SPIplan;
303  Portal SPIportal;
304  bool moredata = TRUE;
305  uint32_t TUPLIMIT = 1000;
306  uint32_t ntuples;
307 
308  edge_t *edges = NULL;
309  uint32_t total_tuples = 0;
310 #ifndef _MSC_VER
311  edge_columns_t edge_columns = {.id = -1, .source = -1, .target = -1,
312  .cost = -1, .reverse_cost = -1};
313 #else // _MSC_VER
314  edge_columns_t edge_columns = {-1, -1, -1, -1, -1};
315 #endif // _MSC_VER
316  restrict_t *restricts = NULL;
317  uint32_t total_restrict_tuples = 0;
318  restrict_columns_t restrict_columns = {.target_id = -1, .via_path = -1,
319  .to_cost = -1};
320  int64_t v_max_id = 0;
321  int64_t v_min_id = INT_MAX;
322 
323  /* track if start and end are both in edge tuples */
324  int s_count = 0;
325  int t_count = 0;
326 
327  char *err_msg;
328  int ret = -1;
329  uint32_t z;
330 
331  PGR_DBG("start turn_restrict_shortest_path\n");
332 
333  SPIcode = SPI_connect();
334  if (SPIcode != SPI_OK_CONNECT) {
335  elog(ERROR, "turn_restrict_shortest_path: "
336  "couldn't open a connection to SPI");
337  return -1;
338  }
339 
340  SPIplan = SPI_prepare(sql, 0, NULL);
341  if (SPIplan == NULL) {
342  elog(ERROR, "turn_restrict_shortest_path: "
343  "couldn't create query plan via SPI");
344  return -1;
345  }
346 
347  if ((SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true)) == NULL) {
348  elog(ERROR, "turn_restrict_shortest_path: "
349  "SPI_cursor_open('%s') returns NULL", sql);
350  return -1;
351  }
352 
353  while (moredata == TRUE) {
354  // PGR_DBG("calling SPI_cursor_fetch");
355  SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);
356 
357  if (SPI_tuptable == NULL) {
358  elog(ERROR, "SPI_tuptable is NULL");
359  return finish(SPIcode, -1);
360  }
361 
362  if (edge_columns.id == -1) {
363  if (fetch_edge_columns(SPI_tuptable, &edge_columns,
364  has_reverse_cost) == -1)
365  return finish(SPIcode, ret);
366  }
367 
368  ntuples = SPI_processed;
369 
370  // PGR_DBG("Reading edges: %i - %i", total_tuples, total_tuples+ntuples);
371 
372  total_tuples += ntuples;
373 
374  if (ntuples > 0) {
375  if (!edges)
376  edges = palloc(total_tuples * sizeof(edge_t));
377  else
378  edges = repalloc(edges, total_tuples * sizeof(edge_t));
379 
380  if (edges == NULL) {
381  elog(ERROR, "Out of memory");
382  return finish(SPIcode, ret);
383  }
384 
385  uint32_t t;
386  SPITupleTable *tuptable = SPI_tuptable;
387  TupleDesc tupdesc = SPI_tuptable->tupdesc;
388 
389  for (t = 0; t < ntuples; t++) {
390  // if (t%100 == 0) { PGR_DBG(" t: %i", t); }
391  HeapTuple tuple = tuptable->vals[t];
392  fetch_edge(&tuple, &tupdesc, &edge_columns,
393  &edges[total_tuples - ntuples + t]);
394  }
395  // PGR_DBG("calling SPI_freetuptable");
396  SPI_freetuptable(tuptable);
397  // PGR_DBG("back from SPI_freetuptable");
398  } else {
399  moredata = FALSE;
400  }
401  }
402  SPI_cursor_close(SPIportal);
403 
404  // defining min and max vertex id
405 
406  // DBG("Total %i edge tuples", total_tuples);
407 
408  for (z = 0; z < total_tuples; z++) {
409  if (edges[z].source < v_min_id)
410  v_min_id = edges[z].source;
411 
412  if (edges[z].source > v_max_id)
413  v_max_id = edges[z].source;
414 
415  if (edges[z].target < v_min_id)
416  v_min_id = edges[z].target;
417 
418  if (edges[z].target > v_max_id)
419  v_max_id = edges[z].target;
420 
421  // DBG("%i <-> %i", v_min_id, v_max_id);
422  }
423 
424  // ::::::::::::::::::::::::::::::::::::
425  // :: reducing vertex id (renumbering)
426  // ::::::::::::::::::::::::::::::::::::
427  for (z = 0; z < total_tuples; z++) {
428  // check if edges[] contains source and target
429  if (dovertex) {
430  if (edges[z].source == start_id || edges[z].target == start_id)
431  ++s_count;
432  if (edges[z].source == end_id || edges[z].target == end_id)
433  ++t_count;
434  } else {
435  if (edges[z].id == start_id)
436  ++s_count;
437  if (edges[z].id == end_id)
438  ++t_count;
439  }
440 
441  edges[z].source -= v_min_id;
442  edges[z].target -= v_min_id;
443  edges[z].cost = edges[z].cost;
444  // PGR_DBG("edgeID: %i SRc:%i - %i, cost: %f",
445  // edges[z].id,edges[z].source, edges[z].target,edges[z].cost);
446  }
447 
448  PGR_DBG("Min vertex id: %ld , Max vid: %ld", v_min_id, v_max_id);
449  PGR_DBG("Total %i edge tuples", total_tuples);
450 
451  if (s_count == 0) {
452  elog(ERROR, "Start id was not found.");
453  return -1;
454  }
455 
456  if (t_count == 0) {
457  elog(ERROR, "Target id was not found.");
458  return -1;
459  }
460 
461  if (dovertex) {
462  start_id -= v_min_id;
463  end_id -= v_min_id;
464  }
465 
466  PGR_DBG("Fetching restriction tuples\n");
467 
468  if (restrict_sql == NULL) {
469  PGR_DBG("Sql for restrictions is null.");
470  } else {
471  SPIplan = SPI_prepare(restrict_sql, 0, NULL);
472  if (SPIplan == NULL) {
473  elog(ERROR, "turn_restrict_shortest_path: "
474  "couldn't create query plan via SPI");
475  return -1;
476  }
477 
478  if ((SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true)) \
479  == NULL) {
480  elog(ERROR, "turn_restrict_shortest_path:"
481  " SPI_cursor_open('%s') returns NULL", restrict_sql);
482  return -1;
483  }
484 
485  moredata = TRUE;
486  while (moredata == TRUE) {
487  SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);
488 
489  if (restrict_columns.target_id == -1) {
490  if (fetch_restrict_columns(SPI_tuptable, &restrict_columns) \
491  == -1) {
492  PGR_DBG("fetch_restrict_columns failed!");
493  return finish(SPIcode, ret);
494  }
495  }
496 
497  ntuples = SPI_processed;
498  total_restrict_tuples += ntuples;
499 
500  // DBG("Reading Restrictions: %i", total_restrict_tuples);
501 
502  if (ntuples > 0) {
503  if (!restricts)
504  restricts = palloc(total_restrict_tuples * sizeof(restrict_t));
505  else
506  restricts = repalloc(restricts,
507  total_restrict_tuples * sizeof(restrict_t));
508 
509  if (restricts == NULL) {
510  elog(ERROR, "Out of memory");
511  return finish(SPIcode, ret);
512  }
513 
514  uint32_t t;
515  SPITupleTable *tuptable = SPI_tuptable;
516  TupleDesc tupdesc = SPI_tuptable->tupdesc;
517 
518  for (t = 0; t < ntuples; t++) {
519  HeapTuple tuple = tuptable->vals[t];
520  fetch_restrict(&tuple, &tupdesc, &restrict_columns,
521  &restricts[total_restrict_tuples - ntuples + t]);
522  }
523  SPI_freetuptable(tuptable);
524  } else {
525  moredata = FALSE;
526  }
527  }
528  SPI_cursor_close(SPIportal);
529  }
530 
531 #ifdef DEBUG_OFF
532  int t;
533  for (t=0; t < total_restrict_tuples; t++) {
534  PGR_DBG("restricts: %.2f, %i, %i, %i, %i, %i, %i",
535  restricts[t].to_cost, restricts[t].target_id, restricts[t].via[0],
536  restricts[t].via[1], restricts[t].via[2], restricts[t].via[3],
537  restricts[t].via[4]);
538  }
539 #endif
540 
541  PGR_DBG("Total %i restriction tuples", total_restrict_tuples);
542 
543  if (dovertex) {
544  PGR_DBG("Calling trsp_node_wrapper\n");
547  #if defined(__MINGW64__)
548  // elog(NOTICE,"Calling trsp_node_wrapper\n");
549  #endif
550  ret = trsp_node_wrapper(edges, total_tuples,
551  restricts, total_restrict_tuples,
552  start_id, end_id,
553  directed, has_reverse_cost,
554  path, path_count, &err_msg);
555  } else {
556  PGR_DBG("Calling trsp_edge_wrapper\n");
557  ret = trsp_edge_wrapper(edges, total_tuples,
558  restricts, total_restrict_tuples,
559  start_id, start_pos, end_id, end_pos,
560  directed, has_reverse_cost,
561  path, path_count, &err_msg);
562  }
563 
564  PGR_DBG("Message received from inside:");
565  PGR_DBG("%s", err_msg);
566 
567  // DBG("SIZE %i\n",*path_count);
568 
569  // ::::::::::::::::::::::::::::::::
570  // :: restoring original vertex id
571  // ::::::::::::::::::::::::::::::::
572  for (z = 0; z < *path_count; z++) {
573  // PGR_DBG("vetex %i\n",(*path)[z].vertex_id);
574  if (z || (*path)[z].vertex_id != -1)
575  (*path)[z].vertex_id += v_min_id;
576  }
577 
578  PGR_DBG("ret = %i\n", ret);
579 
580  PGR_DBG("*path_count = %ld\n", *path_count);
581 
582  if (ret < 0) {
583  // elog(ERROR, "Error computing path: %s", err_msg);
584  ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED),
585  errmsg("Error computing path: %s", err_msg)));
586  }
587 
588  return finish(SPIcode, ret);
589 }
int64_t source
Definition: trsp_types.h:57
static void fetch_edge(HeapTuple *tuple, TupleDesc *tupdesc, edge_columns_t *edge_columns, edge_t *target_edge)
Definition: trsp.c:201
#define PGR_DBG(...)
Definition: debug_macro.h:34
int id
Definition: trsp.c:74
double cost
Definition: trsp_types.h:59
int trsp_node_wrapper(edge_t *edges, size_t edge_count, restrict_t *restricts, size_t restrict_count, int64_t start_vertex, int64_t end_vertex, bool directed, bool has_reverse_cost, path_element_tt **path, size_t *path_count, char **err_msg)
Definition: trsp_core.cpp:35
static int fetch_edge_columns(SPITupleTable *tuptable, edge_columns_t *edge_columns, bool has_reverse_cost)
Definition: trsp.c:146
static int finish(int code, int ret)
Definition: trsp.c:101
static int fetch_restrict_columns(SPITupleTable *tuptable, restrict_columns_t *restrict_columns)
Definition: trsp.c:116
int64_t target
Definition: trsp_types.h:58
int trsp_edge_wrapper(edge_t *edges, size_t edge_count, restrict_t *restricts, size_t restrict_count, int64_t start_edge, double start_pos, int64_t end_edge, double end_pos, bool directed, bool has_reverse_cost, path_element_tt **path, size_t *path_count, char **err_msg)
Definition: trsp_core.cpp:83
int target_id
Definition: trsp.c:82
static void fetch_restrict(HeapTuple *tuple, TupleDesc *tupdesc, restrict_columns_t *restrict_columns, restrict_t *rest)
Definition: trsp.c:247
#define TUPLIMIT
Definition: alpha.c:50

Here is the call graph for this function:

Here is the caller graph for this function:

static void fetch_edge ( HeapTuple *  tuple,
TupleDesc *  tupdesc,
edge_columns_t edge_columns,
edge_t target_edge 
)
static

Definition at line 201 of file trsp.c.

References edge_t::cost, edge_columns::cost, edge_t::id, edge_columns::id, edge_t::reverse_cost, edge_columns::reverse_cost, edge_t::source, edge_columns::source, edge_t::target, and edge_columns::target.

Referenced by compute_trsp().

202  {
203  Datum binval;
204  bool isnull;
205 
206  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->id, &isnull);
207  if (isnull)
208  elog(ERROR, "id contains a null value");
209  target_edge->id = DatumGetInt32(binval);
210 
211  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->source, &isnull);
212  if (isnull)
213  elog(ERROR, "source contains a null value");
214  target_edge->source = DatumGetInt32(binval);
215 
216  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->target, &isnull);
217  if (isnull)
218  elog(ERROR, "target contains a null value");
219  target_edge->target = DatumGetInt32(binval);
220 
221  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->cost, &isnull);
222  if (isnull)
223  elog(ERROR, "cost contains a null value");
224  target_edge->cost = DatumGetFloat8(binval);
225 
226  if (edge_columns->reverse_cost != -1) {
227  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->reverse_cost,
228  &isnull);
229  if (isnull)
230  elog(ERROR, "reverse_cost contains a null value");
231  target_edge->reverse_cost = DatumGetFloat8(binval);
232  }
233 
234  /*
235  PGR_DBG("edge: %i, %i, %i, %f, %f", target_edge->id, target_edge->source,
236  target_edge->target, target_edge->cost, target_edge->reverse_cost);
237  */
238 }
int reverse_cost
Definition: trsp.c:78
int64_t source
Definition: trsp_types.h:57
int id
Definition: trsp.c:74
double cost
Definition: trsp_types.h:59
int cost
Definition: trsp.c:77
int source
Definition: trsp.c:75
int64_t target
Definition: trsp_types.h:58
int target
Definition: trsp.c:76
double reverse_cost
Definition: trsp_types.h:60
int64_t id
Definition: trsp_types.h:56

Here is the caller graph for this function:

static int fetch_edge_columns ( SPITupleTable *  tuptable,
edge_columns_t edge_columns,
bool  has_reverse_cost 
)
static

Definition at line 146 of file trsp.c.

References edge_columns::cost, edge_columns::id, PGR_DBG, edge_columns::reverse_cost, edge_columns::source, and edge_columns::target.

Referenced by compute_trsp().

147  {
148  edge_columns->id = SPI_fnumber(tuptable->tupdesc, "id");
149  edge_columns->source = SPI_fnumber(tuptable->tupdesc, "source");
150  edge_columns->target = SPI_fnumber(tuptable->tupdesc, "target");
151  edge_columns->cost = SPI_fnumber(tuptable->tupdesc, "cost");
152  if (edge_columns->id == SPI_ERROR_NOATTRIBUTE ||
153  edge_columns->source == SPI_ERROR_NOATTRIBUTE ||
154  edge_columns->target == SPI_ERROR_NOATTRIBUTE ||
155  edge_columns->cost == SPI_ERROR_NOATTRIBUTE) {
156  elog(ERROR, "Error, query must return columns "
157  "'id', 'source', 'target' and 'cost'");
158  return -1;
159  }
160 
161  if (SPI_gettypeid(tuptable->tupdesc, edge_columns->source) != INT4OID ||
162  SPI_gettypeid(tuptable->tupdesc, edge_columns->target) != INT4OID ||
163  SPI_gettypeid(tuptable->tupdesc, edge_columns->cost) != FLOAT8OID) {
164  elog(ERROR, "Error, columns 'source', 'target' must be of type int4, "
165  "'cost' must be of type float8");
166  return -1;
167  }
168 
169  PGR_DBG("columns: id %i source %i target %i cost %i",
170  edge_columns->id, edge_columns->source,
171  edge_columns->target, edge_columns->cost);
172 
173  if (has_reverse_cost) {
174  edge_columns->reverse_cost = SPI_fnumber(tuptable->tupdesc,
175  "reverse_cost");
176 
177  if (edge_columns->reverse_cost == SPI_ERROR_NOATTRIBUTE) {
178  elog(ERROR, "Error, reverse_cost is used, but query did't return "
179  "'reverse_cost' column");
180  return -1;
181  }
182 
183  if (SPI_gettypeid(tuptable->tupdesc, edge_columns->reverse_cost)
184  != FLOAT8OID) {
185  elog(ERROR, "Error, columns 'reverse_cost' must be of type float8");
186  return -1;
187  }
188 
189  PGR_DBG("columns: reverse_cost cost %i", edge_columns->reverse_cost);
190  }
191 
192  return 0;
193 }
int reverse_cost
Definition: trsp.c:78
#define PGR_DBG(...)
Definition: debug_macro.h:34
int id
Definition: trsp.c:74
int cost
Definition: trsp.c:77
int source
Definition: trsp.c:75
int target
Definition: trsp.c:76

Here is the caller graph for this function:

static void fetch_restrict ( HeapTuple *  tuple,
TupleDesc *  tupdesc,
restrict_columns_t restrict_columns,
restrict_t rest 
)
static

Definition at line 247 of file trsp.c.

References MAX_RULE_LENGTH, restrict_struct::target_id, restrict_columns::target_id, restrict_struct::to_cost, restrict_columns::to_cost, restrict_struct::via, and restrict_columns::via_path.

Referenced by compute_trsp().

248  {
249  Datum binval;
250  bool isnull;
251  int t;
252 
253  for (t = 0; t < MAX_RULE_LENGTH; ++t)
254  rest->via[t] = -1;
255 
256  binval = SPI_getbinval(*tuple, *tupdesc, restrict_columns->target_id,
257  &isnull);
258  if (isnull)
259  elog(ERROR, "target_id contains a null value");
260  rest->target_id = DatumGetInt32(binval);
261 
262  binval = SPI_getbinval(*tuple, *tupdesc, restrict_columns->to_cost, &isnull);
263  if (isnull)
264  elog(ERROR, "to_cost contains a null value");
265  rest->to_cost = DatumGetFloat8(binval);
266  char *str = DatumGetCString(SPI_getvalue(*tuple, *tupdesc,
267  restrict_columns->via_path));
268 
269  // PGR_DBG("restriction: %f, %i, %s", rest->to_cost, rest->target_id, str);
270 
271  if (str != NULL) {
272  char* pch = NULL;
273  int ci = 0;
274 
275  pch = (char *)strtok(str, " ,");
276 
277  while (pch != NULL && ci < MAX_RULE_LENGTH) {
278  rest->via[ci] = atoi(pch);
279  // PGR_DBG(" rest->via[%i]=%i", ci, rest->via[ci]);
280  ci++;
281  pch = (char *)strtok(NULL, " ,");
282  }
283  }
284 }
int to_cost
Definition: trsp.c:84
int via[5]
Definition: trsp.h:42
int via_path
Definition: trsp.c:83
int target_id
Definition: trsp.h:40
float8 to_cost
Definition: trsp.h:41
int target_id
Definition: trsp.c:82
#define MAX_RULE_LENGTH
Definition: trsp.h:25

Here is the caller graph for this function:

static int fetch_restrict_columns ( SPITupleTable *  tuptable,
restrict_columns_t restrict_columns 
)
static

Definition at line 116 of file trsp.c.

References restrict_columns::target_id, restrict_columns::to_cost, and restrict_columns::via_path.

Referenced by compute_trsp().

117  {
118  restrict_columns->target_id = SPI_fnumber(tuptable->tupdesc, "target_id");
119  restrict_columns->via_path = SPI_fnumber(tuptable->tupdesc, "via_path");
120  restrict_columns->to_cost = SPI_fnumber(tuptable->tupdesc, "to_cost");
121  if (restrict_columns->target_id == SPI_ERROR_NOATTRIBUTE ||
122  restrict_columns->via_path == SPI_ERROR_NOATTRIBUTE ||
123  restrict_columns->to_cost == SPI_ERROR_NOATTRIBUTE) {
124  elog(ERROR, "Error, restriction query must return columns "
125  "'target_id', 'via_path' and 'to_cost'");
126  return -1;
127  }
128 
129  if (SPI_gettypeid(tuptable->tupdesc,
130  restrict_columns->target_id) != INT4OID ||
131  SPI_gettypeid(tuptable->tupdesc, restrict_columns->via_path) != TEXTOID ||
132  SPI_gettypeid(tuptable->tupdesc, restrict_columns->to_cost) != FLOAT8OID) {
133  elog(ERROR, "Error, restriction columns 'target_id' must be of type int4,"
134  "'via_path' must be of type text, 'to_cost' must be of type float8");
135  return -1;
136  }
137 
138  return 0;
139 }
int to_cost
Definition: trsp.c:84
int via_path
Definition: trsp.c:83
int target_id
Definition: trsp.c:82

Here is the caller graph for this function:

static int finish ( int  code,
int  ret 
)
static

Definition at line 101 of file trsp.c.

References PGR_DBG.

Referenced by compute_trsp().

101  {
102  PGR_DBG("In finish, trying to disconnect from spi %d", ret);
103  code = SPI_finish();
104  if (code != SPI_OK_FINISH) {
105  elog(ERROR, "couldn't disconnect from SPI");
106  return -1;
107  }
108  return ret;
109 }
#define PGR_DBG(...)
Definition: debug_macro.h:34

Here is the caller graph for this function:

PG_FUNCTION_INFO_V1 ( turn_restrict_shortest_path_edge  )

Referenced by compute_trsp().

Here is the caller graph for this function:

PGDLLEXPORT Datum turn_restrict_shortest_path_edge ( PG_FUNCTION_ARGS  )

Definition at line 732 of file trsp.c.

References compute_trsp(), path_element::cost, path_element::edge_id, if(), PGR_DBG, and path_element::vertex_id.

Referenced by compute_trsp().

732  {
733  FuncCallContext *funcctx;
734 #if 0
735  uint32_t call_cntr;
736  uint32_t max_calls;
737 #endif
738  TupleDesc tuple_desc;
739  path_element_tt *path;
740  char * sql;
741 
742  // stuff done only on the first call of the function
743  if (SRF_IS_FIRSTCALL()) {
744  MemoryContext oldcontext;
745  size_t path_count = 0;
746 #ifdef DEBUG
747  int ret = -1;
748 #endif
749  int i;
750  double s_pos;
751  double e_pos;
752 
753  // create a function context for cross-call persistence
754  funcctx = SRF_FIRSTCALL_INIT();
755 
756  // switch to memory context appropriate for multiple function calls
757  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
758 
759  // verify that the first 5 args are not NULL
760  for (i = 0; i < 7; i++) {
761  if (i == 2 || i == 4) continue;
762  if (PG_ARGISNULL(i)) {
763  elog(ERROR, "turn_restrict_shortest_path(): "
764  "Argument %i may not be NULL", i+1);
765  }
766  }
767 
768  if (PG_ARGISNULL(2)) {
769  s_pos = 0.5;
770  } else {
771  s_pos = PG_GETARG_FLOAT8(2);
772  if (s_pos < 0.0) s_pos = 0.5;
773  if (s_pos > 1.0) s_pos = 0.5;
774  }
775 
776  if (PG_ARGISNULL(4)) {
777  e_pos = 0.5;
778  } else {
779  e_pos = PG_GETARG_FLOAT8(4);
780  if (e_pos < 0.0) e_pos = 0.5;
781  if (e_pos > 1.0) e_pos = 0.5;
782  }
783 
784  if (PG_ARGISNULL(7)) {
785  sql = NULL;
786  } else {
787  sql = text_to_cstring(PG_GETARG_TEXT_P(7));
788  if (strlen(sql) == 0)
789  sql = NULL;
790  }
791 
792  PGR_DBG("Calling compute_trsp");
793 
794 #ifdef DEBUG
795  ret =
796 #endif
797  compute_trsp(text_to_cstring(PG_GETARG_TEXT_P(0)),
798  0, // sdo edge
799  PG_GETARG_INT32(1),
800  s_pos,
801  PG_GETARG_INT32(3),
802  e_pos,
803  PG_GETARG_BOOL(5),
804  PG_GETARG_BOOL(6),
805  sql,
806  &path, &path_count);
807 #ifdef DEBUG
808  double total_cost = 0;
809  PGR_DBG("Ret is %i", ret);
810  if (ret >= 0) {
811  int i;
812  for (i = 0; i < path_count; i++) {
813  // PGR_DBG("Step %i vertex_id %i ", i, path[i].vertex_id);
814  // PGR_DBG(" edge_id %i ", path[i].edge_id);
815  // PGR_DBG(" cost %f ", path[i].cost);
816  total_cost+=path[i].cost;
817  }
818  }
819  PGR_DBG("Total cost is: %f", total_cost);
820 #endif
821 
822  // total number of tuples to be returned
823 #if 1
824 #if PGSQL_VERSION > 95
825  funcctx->max_calls = path_count;
826 #else
827  funcctx->max_calls = (uint32_t)path_count;
828 #endif
829 #else
830  funcctx->max_calls = path_count;
831 #endif
832  funcctx->user_fctx = path;
833 
834  funcctx->tuple_desc =
835  BlessTupleDesc(RelationNameGetTupleDesc("pgr_costResult"));
836 
837  MemoryContextSwitchTo(oldcontext);
838  }
839 
840  // stuff done on every call of the function
841  funcctx = SRF_PERCALL_SETUP();
842 
843 #if 0
844  call_cntr = funcctx->call_cntr;
845  max_calls = funcctx->max_calls;
846 #endif
847  tuple_desc = funcctx->tuple_desc;
848  path = (path_element_tt*) funcctx->user_fctx;
849 
850  if (funcctx->call_cntr < funcctx->max_calls) {
851  // do when there is more left to send
852  HeapTuple tuple;
853  Datum result;
854  Datum *values;
855  bool* nulls;
856 
857  values = palloc(4 * sizeof(Datum));
858  nulls = palloc(4 * sizeof(char));
859 
860  values[0] = Int32GetDatum(funcctx->call_cntr);
861  nulls[0] = false;
862  values[1] = Int32GetDatum(path[funcctx->call_cntr].vertex_id);
863  nulls[1] = false;
864  values[2] = Int32GetDatum(path[funcctx->call_cntr].edge_id);
865  nulls[2] = false;
866  values[3] = Float8GetDatum(path[funcctx->call_cntr].cost);
867  nulls[3] = false;
868 
869  tuple = heap_form_tuple(tuple_desc, values, nulls);
870 
871  // make the tuple into a datum
872  result = HeapTupleGetDatum(tuple);
873 
874  // clean up (this is not really necessary)
875  pfree(values);
876  pfree(nulls);
877 
878  SRF_RETURN_NEXT(funcctx, result);
879  } else { // do when there is no more left
880  PGR_DBG("Going to free path");
881  if (path) free(path);
882  SRF_RETURN_DONE(funcctx);
883  }
884 }
#define PGR_DBG(...)
Definition: debug_macro.h:34
long edge_id
Definition: trsp.h:48
float8 cost
Definition: trsp.h:49
if(DOXYGEN_FOUND) configure_file($
Definition: CMakeLists.txt:13
static int compute_trsp(char *sql, int dovertex, int64_t start_id, double start_pos, int64_t end_id, double end_pos, bool directed, bool has_reverse_cost, char *restrict_sql, path_element_tt **path, size_t *path_count)
Definition: trsp.c:288
long vertex_id
Definition: trsp.h:47

Here is the call graph for this function:

Here is the caller graph for this function: