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