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