PGROUTING  2.5
trsp.c File Reference
#include "c_common/postgres_connection.h"
#include "catalog/pg_type.h"
#include "c_common/debug_macro.h"
#include "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_vertex)
 
 PG_FUNCTION_INFO_V1 (turn_restrict_shortest_path_edge)
 
PGDLLEXPORT Datum turn_restrict_shortest_path_edge (PG_FUNCTION_ARGS)
 
PGDLLEXPORT Datum turn_restrict_shortest_path_vertex (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 286 of file trsp.c.

References edge::cost, edges, fetch_edge(), fetch_edge_columns(), fetch_restrict(), fetch_restrict_columns(), finish(), edge_columns::id, PG_FUNCTION_INFO_V1(), PGR_DBG, edge::source, edge_columns::source, edge::target, edge_columns::target, restrict_columns::target_id, trsp_edge_wrapper(), trsp_node_wrapper(), TUPLIMIT, and turn_restrict_shortest_path_vertex().

Referenced by turn_restrict_shortest_path_edge(), and turn_restrict_shortest_path_vertex().

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

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 199 of file trsp.c.

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

Referenced by compute_trsp().

200  {
201  Datum binval;
202  bool isnull;
203 
204  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->id, &isnull);
205  if (isnull)
206  elog(ERROR, "id contains a null value");
207  target_edge->id = DatumGetInt32(binval);
208 
209  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->source, &isnull);
210  if (isnull)
211  elog(ERROR, "source contains a null value");
212  target_edge->source = DatumGetInt32(binval);
213 
214  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->target, &isnull);
215  if (isnull)
216  elog(ERROR, "target contains a null value");
217  target_edge->target = DatumGetInt32(binval);
218 
219  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->cost, &isnull);
220  if (isnull)
221  elog(ERROR, "cost contains a null value");
222  target_edge->cost = DatumGetFloat8(binval);
223 
224  if (edge_columns->reverse_cost != -1) {
225  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->reverse_cost,
226  &isnull);
227  if (isnull)
228  elog(ERROR, "reverse_cost contains a null value");
229  target_edge->reverse_cost = DatumGetFloat8(binval);
230  }
231 
232  /*
233  PGR_DBG("edge: %i, %i, %i, %f, %f", target_edge->id, target_edge->source,
234  target_edge->target, target_edge->cost, target_edge->reverse_cost);
235  */
236 }
int reverse_cost
Definition: trsp.c:76
float8 cost
Definition: trsp.h:35
long id
Definition: trsp.h:32
int id
Definition: trsp.c:72
int cost
Definition: trsp.c:75
int source
Definition: trsp.c:73
int target
Definition: trsp.c:74
long target
Definition: trsp.h:34
float8 reverse_cost
Definition: trsp.h:36
long source
Definition: trsp.h:33

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 144 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().

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

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 245 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().

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

Here is the caller graph for this function:

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

Definition at line 114 of file trsp.c.

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

Referenced by compute_trsp().

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

Here is the caller graph for this function:

static int finish ( int  code,
int  ret 
)
static

Definition at line 99 of file trsp.c.

References PGR_DBG.

Referenced by compute_trsp().

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

Here is the caller graph for this function:

PG_FUNCTION_INFO_V1 ( turn_restrict_shortest_path_vertex  )

Referenced by compute_trsp(), and turn_restrict_shortest_path_vertex().

Here is the caller graph for this function:

PG_FUNCTION_INFO_V1 ( turn_restrict_shortest_path_edge  )
PGDLLEXPORT Datum turn_restrict_shortest_path_edge ( PG_FUNCTION_ARGS  )

Definition at line 729 of file trsp.c.

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

Referenced by turn_restrict_shortest_path_vertex().

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

Here is the call graph for this function:

Here is the caller graph for this function:

PGDLLEXPORT Datum turn_restrict_shortest_path_vertex ( PG_FUNCTION_ARGS  )

Definition at line 593 of file trsp.c.

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

Referenced by compute_trsp().

593  {
594  FuncCallContext *funcctx;
595 #if 0
596  uint32_t call_cntr;
597  int max_calls;
598 #endif
599  TupleDesc tuple_desc;
600  path_element_tt *path;
601  char * sql;
602 
603 
604  // stuff done only on the first call of the function
605  if (SRF_IS_FIRSTCALL()) {
606  MemoryContext oldcontext;
607  size_t path_count = 0;
608 
609  int ret = -1;
610  if (ret == -1) {} // to avoid warning set but not used
611 
612  int i;
613 
614  // create a function context for cross-call persistence
615  funcctx = SRF_FIRSTCALL_INIT();
616 
617  // switch to memory context appropriate for multiple function calls
618  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
619 
620  // verify that the first 5 args are not NULL
621  for (i = 0; i < 5; i++)
622  if (PG_ARGISNULL(i)) {
623  elog(ERROR, "turn_restrict_shortest_path(): "
624  "Argument %i may not be NULL", i+1);
625  }
626 
627  if (PG_ARGISNULL(5)) {
628  sql = NULL;
629  } else {
630  sql = text_to_cstring(PG_GETARG_TEXT_P(5));
631  if (strlen(sql) == 0)
632  sql = NULL;
633  }
634 
635  PGR_DBG("Calling compute_trsp");
636 
637 
638  ret = compute_trsp(text_to_cstring(PG_GETARG_TEXT_P(0)),
639  1, // do vertex
640  PG_GETARG_INT32(1),
641  0.5,
642  PG_GETARG_INT32(2),
643  0.5,
644  PG_GETARG_BOOL(3),
645  PG_GETARG_BOOL(4),
646  sql,
647  &path, &path_count);
648 #ifdef DEBUG
649  double total_cost = 0;
650  PGR_DBG("Ret is %i", ret);
651  if (ret >= 0) {
652  int i;
653  for (i = 0; i < path_count; i++) {
654  // PGR_DBG("Step %i vertex_id %i ", i, path[i].vertex_id);
655  // PGR_DBG(" edge_id %i ", path[i].edge_id);
656  // PGR_DBG(" cost %f ", path[i].cost);
657  total_cost += path[i].cost;
658  }
659  }
660  PGR_DBG("Total cost is: %f", total_cost);
661 #endif
662 
663  // total number of tuples to be returned
664 #if 1
665 #if PGSQL_VERSION > 95
666  funcctx->max_calls = path_count;
667 #else
668  funcctx->max_calls = (uint32_t)path_count;
669 #endif
670 #else
671  funcctx->max_calls = path_count;
672 #endif
673  funcctx->user_fctx = path;
674 
675  funcctx->tuple_desc =
676  BlessTupleDesc(RelationNameGetTupleDesc("pgr_costResult"));
677 
678  MemoryContextSwitchTo(oldcontext);
679  }
680 
681  // stuff done on every call of the function
682  funcctx = SRF_PERCALL_SETUP();
683 
684 #if 0
685  call_cntr = funcctx->call_cntr;
686  max_calls = funcctx->max_calls;
687 #endif
688  tuple_desc = funcctx->tuple_desc;
689  path = (path_element_tt*) funcctx->user_fctx;
690 
691  if (funcctx->call_cntr < funcctx->max_calls) {
692  // do when there is more left to send
693  HeapTuple tuple;
694  Datum result;
695  Datum *values;
696  bool* nulls;
697 
698  values = palloc(4 * sizeof(Datum));
699  nulls = palloc(4 * sizeof(char));
700 
701  values[0] = Int32GetDatum(funcctx->call_cntr);
702  nulls[0] = false;
703  values[1] = Int32GetDatum(path[funcctx->call_cntr].vertex_id);
704  nulls[1] = false;
705  values[2] = Int32GetDatum(path[funcctx->call_cntr].edge_id);
706  nulls[2] = false;
707  values[3] = Float8GetDatum(path[funcctx->call_cntr].cost);
708  nulls[3] = false;
709 
710  tuple = heap_form_tuple(tuple_desc, values, nulls);
711 
712  // make the tuple into a datum
713  result = HeapTupleGetDatum(tuple);
714 
715  // clean up (this is not really necessary)
716  pfree(values);
717  pfree(nulls);
718 
719  SRF_RETURN_NEXT(funcctx, result);
720  } else { // do when there is no more left
721  PGR_DBG("Going to free path");
722  if (path) free(path);
723  SRF_RETURN_DONE(funcctx);
724  }
725 }
#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:286
long vertex_id
Definition: trsp.h:47

Here is the call graph for this function:

Here is the caller graph for this function: