PGROUTING  2.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
edges_input.c
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 File: edges_input.c
3 
4 Copyright (c) 2015 Celia Virginia Vergara Castillo
5 vicky_vergara@hotmail.com
6 
7 ------
8 
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 
23 ********************************************************************PGR-GNU*/
24 
25 #include "./postgres_connection.h"
26 #include "./debug_macro.h"
27 #include "./pgr_types.h"
28 #include "./get_check_data.h"
29 #include "./edges_input.h"
30 #include "./time_msg.h"
31 
32 static
34  HeapTuple *tuple,
35  TupleDesc *tupdesc,
36  Column_info_t info[5],
37  int64_t *default_id,
39  size_t *valid_edges) {
40  if (column_found(info[0].colNumber)) {
41  edge->id = pgr_SPI_getBigInt(tuple, tupdesc, info[0]);
42  } else {
43  edge->id = *default_id;
44  ++(*default_id);
45  }
46 
47  edge->source = pgr_SPI_getBigInt(tuple, tupdesc, info[1]);
48  edge->target = pgr_SPI_getBigInt(tuple, tupdesc, info[2]);
49  edge->going = pgr_SPI_getFloat8(tuple, tupdesc, info[3]) > 0 ? true : false;
50  edge->coming = (column_found(info[4].colNumber) && pgr_SPI_getFloat8(tuple, tupdesc, info[4]) > 0) ? true : false;
51 
52  (*valid_edges)++;
53 }
54 
55 static
57  HeapTuple *tuple,
58  TupleDesc *tupdesc,
59  Column_info_t info[5],
60  int64_t *default_id,
61  float8 default_rcost,
63  size_t *valid_edges,
64  bool normal) {
65  if (column_found(info[0].colNumber)) {
66  edge->id = pgr_SPI_getBigInt(tuple, tupdesc, info[0]);
67  } else {
68  edge->id = *default_id;
69  ++(*default_id);
70  }
71 
72  if (normal) {
73  edge->source = pgr_SPI_getBigInt(tuple, tupdesc, info[1]);
74  edge->target = pgr_SPI_getBigInt(tuple, tupdesc, info[2]);
75  } else {
76  edge->target = pgr_SPI_getBigInt(tuple, tupdesc, info[1]);
77  edge->source = pgr_SPI_getBigInt(tuple, tupdesc, info[2]);
78  }
79 
80  edge->cost = pgr_SPI_getFloat8(tuple, tupdesc, info[3]);
81 
82  if (column_found(info[4].colNumber)) {
83  edge->reverse_cost = pgr_SPI_getFloat8(tuple, tupdesc, info[4]);
84  } else {
85  edge->reverse_cost = default_rcost;
86  }
87 
88  *valid_edges = edge->cost < 0? *valid_edges: *valid_edges + 1;
89  *valid_edges = edge->reverse_cost < 0? *valid_edges: *valid_edges + 1;
90 }
91 
92 static
94  HeapTuple *tuple,
95  TupleDesc *tupdesc,
96  Column_info_t info[9],
97  int64_t *default_id,
98  float8 default_rcost,
100  size_t *valid_edges,
101  bool normal) {
102  if (column_found(info[0].colNumber)) {
103  edge->id = pgr_SPI_getBigInt(tuple, tupdesc, info[0]);
104  } else {
105  edge->id = *default_id;
106  ++(*default_id);
107  }
108 
109  if (normal) {
110  edge->source = pgr_SPI_getBigInt(tuple, tupdesc, info[1]);
111  edge->target = pgr_SPI_getBigInt(tuple, tupdesc, info[2]);
112  } else {
113  edge->target = pgr_SPI_getBigInt(tuple, tupdesc, info[1]);
114  edge->source = pgr_SPI_getBigInt(tuple, tupdesc, info[2]);
115  }
116  edge->cost = pgr_SPI_getFloat8(tuple, tupdesc, info[3]);
117 
118  if (column_found(info[4].colNumber)) {
119  edge->reverse_cost = pgr_SPI_getFloat8(tuple, tupdesc, info[4]);
120  } else {
121  edge->reverse_cost = default_rcost;
122  }
123 
124  edge->x1 = pgr_SPI_getFloat8(tuple, tupdesc, info[5]);
125  edge->y1 = pgr_SPI_getFloat8(tuple, tupdesc, info[6]);
126  edge->x2 = pgr_SPI_getFloat8(tuple, tupdesc, info[7]);
127  edge->y2 = pgr_SPI_getFloat8(tuple, tupdesc, info[8]);
128 
129  *valid_edges = edge->cost < 0? *valid_edges: *valid_edges + 1;
130  *valid_edges = edge->reverse_cost < 0? *valid_edges: *valid_edges + 1;
131 }
132 
133 static
134 void
136  char *sql,
138  size_t *total_edges,
139  bool normal) {
140  clock_t start_t = clock();
141 
142  const int tuple_limit = 1000000;
143 
144  size_t ntuples;
145  size_t total_tuples;
146  size_t valid_edges;
147 
148  Column_info_t info[9];
149 
150  info[0].name = strdup("id");
151  info[1].name = strdup("source");
152  info[2].name = strdup("target");
153  info[3].name = strdup("cost");
154  info[4].name = strdup("reverse_cost");
155  info[5].name = strdup("x1");
156  info[6].name = strdup("y1");
157  info[7].name = strdup("x2");
158  info[8].name = strdup("y2");
159 
160  int i;
161  for (i = 0; i < 3; ++i) {
162  info[i].colNumber = -1;
163  info[i].type = 0;
164  info[i].strict = true;
165  info[i].eType = ANY_INTEGER;
166  }
167  for (i = 3; i < 9; ++i) {
168  info[i].colNumber = -1;
169  info[i].type = 0;
170  info[i].strict = true;
171  info[i].eType = ANY_NUMERICAL;
172  }
173  /*
174  * reverse_cost is optional
175  */
176  info[4].strict = false;
177 
178 
179  void *SPIplan;
180  SPIplan = pgr_SPI_prepare(sql);
181 
182  Portal SPIportal;
183  SPIportal = pgr_SPI_cursor_open(SPIplan);
184 
185 
186  bool moredata = TRUE;
187  (*total_edges) = total_tuples = valid_edges = 0;
188 
189 
190  int64_t default_id = 0;
191  while (moredata == TRUE) {
192  SPI_cursor_fetch(SPIportal, TRUE, tuple_limit);
193  if (total_tuples == 0)
194  pgr_fetch_column_info(info, 9);
195 
196  ntuples = SPI_processed;
197  total_tuples += ntuples;
198 
199  if (ntuples > 0) {
200  if ((*edges) == NULL)
201  (*edges) = (Pgr_edge_xy_t *)
202  palloc0(total_tuples * sizeof(Pgr_edge_xy_t));
203  else
204  (*edges) = (Pgr_edge_xy_t *)
205  repalloc((*edges), total_tuples * sizeof(Pgr_edge_xy_t));
206 
207  if ((*edges) == NULL) {
208  elog(ERROR, "Out of memory");
209  }
210 
211  size_t t;
212  SPITupleTable *tuptable = SPI_tuptable;
213  TupleDesc tupdesc = SPI_tuptable->tupdesc;
214  for (t = 0; t < ntuples; t++) {
215  HeapTuple tuple = tuptable->vals[t];
216  fetch_edge_with_xy(&tuple, &tupdesc, info,
217  &default_id, -1,
218  &(*edges)[total_tuples - ntuples + t],
219  &valid_edges, normal);
220  }
221  SPI_freetuptable(tuptable);
222  } else {
223  moredata = FALSE;
224  }
225  }
226 
227  SPI_cursor_close(SPIportal);
228 
229  if (total_tuples == 0 || valid_edges == 0) {
230  PGR_DBG("No edges found");
231  }
232 
233  (*total_edges) = total_tuples;
234  PGR_DBG("Finish reading %ld edges", total_tuples);
235  time_msg("reading edges", start_t, clock());
236 }
237 
238 
239 
240 static
241 void
243  char *sql,
244  pgr_edge_t **edges,
245  size_t *totalTuples,
246  bool ignore_id,
247  bool normal) {
248  clock_t start_t = clock();
249 
250  const int tuple_limit = 1000000;
251 
252  size_t ntuples;
253  size_t total_tuples;
254  size_t valid_edges;
255 
256  Column_info_t info[5];
257 
258  int i;
259  for (i = 0; i < 5; ++i) {
260  info[i].colNumber = -1;
261  info[i].type = 0;
262  info[i].strict = true;
263  info[i].eType = ANY_INTEGER;
264  }
265  info[0].name = strdup("id");
266  info[1].name = strdup("source");
267  info[2].name = strdup("target");
268  info[3].name = strdup("cost");
269  info[4].name = strdup("reverse_cost");
270 
271  info[0].strict = !ignore_id;
272  info[4].strict = false;
273 
274  info[3].eType = ANY_NUMERICAL;
275  info[4].eType = ANY_NUMERICAL;
276 
277 
278  void *SPIplan;
279  SPIplan = pgr_SPI_prepare(sql);
280 
281  Portal SPIportal;
282  SPIportal = pgr_SPI_cursor_open(SPIplan);
283 
284 
285  bool moredata = TRUE;
286  (*totalTuples) = total_tuples = valid_edges = 0;
287 
288 
289  int64_t default_id = 0;
290  while (moredata == TRUE) {
291  SPI_cursor_fetch(SPIportal, TRUE, tuple_limit);
292  if (total_tuples == 0)
293  pgr_fetch_column_info(info, 5);
294 
295  ntuples = SPI_processed;
296  total_tuples += ntuples;
297 
298  if (ntuples > 0) {
299  if ((*edges) == NULL)
300  (*edges) = (pgr_edge_t *)
301  palloc0(total_tuples * sizeof(pgr_edge_t));
302  else
303  (*edges) = (pgr_edge_t *)
304  repalloc((*edges), total_tuples * sizeof(pgr_edge_t));
305 
306  if ((*edges) == NULL) {
307  elog(ERROR, "Out of memory");
308  }
309 
310  size_t t;
311  SPITupleTable *tuptable = SPI_tuptable;
312  TupleDesc tupdesc = SPI_tuptable->tupdesc;
313  for (t = 0; t < ntuples; t++) {
314  HeapTuple tuple = tuptable->vals[t];
315  fetch_edge(&tuple, &tupdesc, info,
316  &default_id, -1,
317  &(*edges)[total_tuples - ntuples + t],
318  &valid_edges,
319  normal);
320  }
321  SPI_freetuptable(tuptable);
322  } else {
323  moredata = FALSE;
324  }
325  }
326 
327  SPI_cursor_close(SPIportal);
328 
329  if (total_tuples == 0 || valid_edges == 0) {
330  PGR_DBG("No edges found");
331  }
332 
333  (*totalTuples) = total_tuples;
334  PGR_DBG("Reading %ld edges", total_tuples);
335  time_msg("reading edges", start_t, clock());
336 }
337 
338 static
339 void
341  char *sql,
342  pgr_edge_t **edges,
343  size_t *totalTuples,
344  bool ignore_id) {
345  clock_t start_t = clock();
346 
347  const int tuple_limit = 1000000;
348 
349  size_t ntuples;
350  size_t total_tuples;
351  size_t valid_edges;
352 
353  Column_info_t info[5];
354 
355  int i;
356  for (i = 0; i < 5; ++i) {
357  info[i].colNumber = -1;
358  info[i].type = 0;
359  info[i].strict = true;
360  info[i].eType = ANY_INTEGER;
361  }
362  info[0].name = strdup("id");
363  info[1].name = strdup("source");
364  info[2].name = strdup("target");
365  info[3].name = strdup("capacity");
366  info[4].name = strdup("reverse_capacity");
367 
368  info[0].strict = !ignore_id;
369  info[4].strict = false;
370 
371  void *SPIplan;
372  SPIplan = pgr_SPI_prepare(sql);
373 
374  Portal SPIportal;
375  SPIportal = pgr_SPI_cursor_open(SPIplan);
376 
377 
378  bool moredata = TRUE;
379  (*totalTuples) = total_tuples = valid_edges = 0;
380 
381 
382  int64_t default_id = 0;
383  while (moredata == TRUE) {
384  SPI_cursor_fetch(SPIportal, TRUE, tuple_limit);
385  if (total_tuples == 0)
386  pgr_fetch_column_info(info, 5);
387 
388  ntuples = SPI_processed;
389  total_tuples += ntuples;
390 
391  if (ntuples > 0) {
392  if ((*edges) == NULL)
393  (*edges) = (pgr_edge_t *)palloc0(total_tuples * sizeof(pgr_flow_t));
394  else
395  (*edges) = (pgr_edge_t *)repalloc((*edges), total_tuples * sizeof(pgr_flow_t));
396 
397  if ((*edges) == NULL) {
398  elog(ERROR, "Out of memory");
399  }
400 
401  size_t t;
402  SPITupleTable *tuptable = SPI_tuptable;
403  TupleDesc tupdesc = SPI_tuptable->tupdesc;
404 
405  for (t = 0; t < ntuples; t++) {
406  HeapTuple tuple = tuptable->vals[t];
407  fetch_edge(&tuple, &tupdesc, info,
408  &default_id, -1,
409  &(*edges)[total_tuples - ntuples + t],
410  &valid_edges,
411  true);
412  }
413  SPI_freetuptable(tuptable);
414  } else {
415  moredata = FALSE;
416  }
417  }
418 
419  SPI_cursor_close(SPIportal);
420 
421  if (total_tuples == 0 || valid_edges == 0) {
422  PGR_DBG("No edges found");
423  }
424 
425  (*totalTuples) = total_tuples;
426  PGR_DBG("Reading %ld edges", total_tuples);
427  time_msg("reading edges", start_t, clock());
428 }
429 
430 static
431 void
433  char *sql,
435  size_t *totalTuples,
436  bool ignore_id) {
437  clock_t start_t = clock();
438 
439  const int tuple_limit = 1000000;
440 
441  size_t ntuples;
442  size_t total_tuples;
443  size_t valid_edges;
444 
445  Column_info_t info[5];
446 
447  int i;
448  for (i = 0; i < 5; ++i) {
449  info[i].colNumber = -1;
450  info[i].type = 0;
451  info[i].strict = true;
452  info[i].eType = ANY_INTEGER;
453  }
454  info[0].name = strdup("id");
455  info[1].name = strdup("source");
456  info[2].name = strdup("target");
457  info[3].name = strdup("going");
458  info[4].name = strdup("coming");
459 
460  info[0].strict = !ignore_id;
461  info[4].strict = false;
462 
463  info[3].eType = ANY_NUMERICAL;
464  info[4].eType = ANY_NUMERICAL;
465 
466 
467  void *SPIplan;
468  SPIplan = pgr_SPI_prepare(sql);
469 
470  Portal SPIportal;
471  SPIportal = pgr_SPI_cursor_open(SPIplan);
472 
473 
474  bool moredata = TRUE;
475  (*totalTuples) = total_tuples = valid_edges = 0;
476 
477 
478  int64_t default_id = 0;
479  while (moredata == TRUE) {
480  SPI_cursor_fetch(SPIportal, TRUE, tuple_limit);
481  if (total_tuples == 0)
482  pgr_fetch_column_info(info, 5);
483 
484  ntuples = SPI_processed;
485  total_tuples += ntuples;
486 
487  if (ntuples > 0) {
488  if ((*edges) == NULL)
489  (*edges) = (pgr_basic_edge_t *)palloc0(
490  total_tuples * sizeof(pgr_basic_edge_t));
491  else
492  (*edges) = (pgr_basic_edge_t *)repalloc(
493  (*edges), total_tuples * sizeof(pgr_basic_edge_t));
494 
495  if ((*edges) == NULL) {
496  elog(ERROR, "Out of memory");
497  }
498 
499  size_t t;
500  SPITupleTable *tuptable = SPI_tuptable;
501  TupleDesc tupdesc = SPI_tuptable->tupdesc;
502 
503  for (t = 0; t < ntuples; t++) {
504  HeapTuple tuple = tuptable->vals[t];
505  fetch_basic_edge(&tuple, &tupdesc, info,
506  &default_id,
507  &(*edges)[total_tuples - ntuples + t],
508  &valid_edges);
509  }
510  SPI_freetuptable(tuptable);
511  } else {
512  moredata = FALSE;
513  }
514  }
515 
516  SPI_cursor_close(SPIportal);
517 
518  if (total_tuples == 0 || valid_edges == 0) {
519  PGR_DBG("No edges found");
520  }
521 
522  (*totalTuples) = total_tuples;
523  PGR_DBG("Reading %ld edges", total_tuples);
524  time_msg("reading edges", start_t, clock());
525 }
526 
527 /* select id, source, target, capacity, reverse_capacity */
528 void
530  char *sql,
531  pgr_edge_t **edges,
532  size_t *total_edges) {
533  bool ignore_id = false;
534  get_edges_flow(sql, edges, total_edges, ignore_id);
535 }
536 
537 /* select id, source, target, cost, reverse_cost */
538 void
540  char *edges_sql,
541  pgr_edge_t **edges,
542  size_t *total_edges) {
543  bool ignore_id = false;
544  bool normal = true;
545  get_edges_5_columns(edges_sql, edges, total_edges, ignore_id, normal);
546 }
547 
548 /* select id, source AS target, target AS source, cost, reverse_cost */
549 void
551  char *edges_sql,
552  pgr_edge_t **edges,
553  size_t *total_edges) {
554  bool ignore_id = false;
555  bool normal = false;
556  get_edges_5_columns(edges_sql, edges, total_edges, ignore_id, normal);
557 }
558 
559 /* select source, target, cost, reverse_cost */
560 void
562  char *edges_sql,
563  pgr_edge_t **edges,
564  size_t *total_edges) {
565  bool ignore_id = true;
566  bool normal = true;
567  get_edges_5_columns(edges_sql, edges, total_edges, ignore_id, normal);
568 }
569 
570 /* select id, source, target, cost, reverse_cost, x1, y1, x2, y2 */
571 void
573  char *edges_sql,
575  size_t *total_edges) {
576  get_edges_9_columns(edges_sql, edges, total_edges, true);
577 }
578 
579 /* select id,
580  * source AS target,
581  * target AS source,
582  * cost, reverse_cost,
583  * x1, y1, x2, y2 */
584 void
586  char *edges_sql,
588  size_t *total_edges) {
589  get_edges_9_columns(edges_sql, edges, total_edges, false);
590 }
591 
592 /* used in flow algorithms */
593 void
595  char *sql,
597  size_t *total_edges) {
598  bool ignore_id = false;
599  get_edges_basic(sql, edges, total_edges, ignore_id);
600 }
int64_t pgr_SPI_getBigInt(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info)
int64_t target
Definition: pgr_types.h:77
double reverse_cost
Definition: pgr_types.h:146
double x1
Definition: pgr_types.h:80
void pgr_get_basic_edges(char *sql, pgr_basic_edge_t **edges, size_t *total_edges)
read basic edges
Definition: edges_input.c:594
int64_t source
Definition: pgr_types.h:143
int64_t target
Definition: pgr_types.h:144
#define PGR_DBG(...)
Definition: debug_macro.h:34
double cost
Definition: pgr_types.h:78
void pgr_get_edges(char *edges_sql, pgr_edge_t **edges, size_t *total_edges)
basic edge_sql
Definition: edges_input.c:539
uint64_t type
Definition: pgr_types.h:200
static void fetch_edge(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info[5], int64_t *default_id, float8 default_rcost, pgr_edge_t *edge, size_t *valid_edges, bool normal)
Definition: edges_input.c:56
int64_t source
Definition: pgr_types.h:76
void time_msg(char *msg, clock_t start_t, clock_t end_t)
Definition: time_msg.c:32
static void fetch_basic_edge(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info[5], int64_t *default_id, pgr_basic_edge_t *edge, size_t *valid_edges)
Definition: edges_input.c:33
char * name
Definition: pgr_types.h:202
double y2
Definition: pgr_types.h:83
void pgr_fetch_column_info(Column_info_t info[], int info_size)
void pgr_get_edges_no_id(char *edges_sql, pgr_edge_t **edges, size_t *total_edges)
edges_sql without id parameter
Definition: edges_input.c:561
double float8
Definition: postgres.h:23
void pgr_get_edges_xy(char *edges_sql, Pgr_edge_xy_t **edges, size_t *total_edges)
Edges with x, y vertices values.
Definition: edges_input.c:572
double x2
Definition: pgr_types.h:82
int64_t id
Definition: pgr_types.h:142
double cost
Definition: pgr_types.h:145
double y1
Definition: pgr_types.h:81
void pgr_get_flow_edges(char *sql, pgr_edge_t **edges, size_t *total_edges)
read edges for flow
Definition: edges_input.c:529
int64_t source
Definition: pgr_types.h:134
double reverse_cost
Definition: pgr_types.h:79
edge_astar_t * edges
Definition: BDATester.cpp:46
int64_t id
Definition: pgr_types.h:75
static void fetch_edge_with_xy(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info[9], int64_t *default_id, float8 default_rcost, Pgr_edge_xy_t *edge, size_t *valid_edges, bool normal)
Definition: edges_input.c:93
int64_t target
Definition: pgr_types.h:135
void pgr_get_edges_xy_reversed(char *edges_sql, Pgr_edge_xy_t **edges, size_t *total_edges)
for many to 1 on aStar
Definition: edges_input.c:585
static void get_edges_flow(char *sql, pgr_edge_t **edges, size_t *totalTuples, bool ignore_id)
Definition: edges_input.c:340
bool column_found(int colNumber)
Portal pgr_SPI_cursor_open(SPIPlanPtr SPIplan)
static void get_edges_basic(char *sql, pgr_basic_edge_t **edges, size_t *totalTuples, bool ignore_id)
Definition: edges_input.c:432
double pgr_SPI_getFloat8(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info)
void pgr_get_edges_reversed(char *edges_sql, pgr_edge_t **edges, size_t *total_edges)
Definition: edges_input.c:550
static void get_edges_9_columns(char *sql, Pgr_edge_xy_t **edges, size_t *total_edges, bool normal)
Definition: edges_input.c:135
SPIPlanPtr pgr_SPI_prepare(char *sql)
static void get_edges_5_columns(char *sql, pgr_edge_t **edges, size_t *totalTuples, bool ignore_id, bool normal)
Definition: edges_input.c:242
expectType eType
Definition: pgr_types.h:203