PGROUTING  2.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
contractGraph.c
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 File: contractGraph.c
3 
4 Generated with Template by:
5 Copyright (c) 2015 pgRouting developers
6 Mail: project@pgrouting.org
7 
8 Function's developer:
9 Copyright (c) 2016 Rohith Reddy
10 Mail:
11 
12 ------
13 
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18 
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23 
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 
28 ********************************************************************PGR-GNU*/
29 
30 #include "./../../common/src/postgres_connection.h"
31 #include "utils/array.h"
32 #include "catalog/pg_type.h"
33 #include "utils/lsyscache.h"
34 
35 #ifndef INT8ARRAYOID
36 #define INT8ARRAYOID 1016
37 #endif
38 
39 #include "./../../common/src/debug_macro.h"
40 #include "./../../common/src/e_report.h"
41 #include "./../../common/src/time_msg.h"
42 #include "./../../common/src/pgr_types.h"
43 #include "./../../common/src/edges_input.h"
44 #include "./../../common/src/arrays_input.h"
45 #include "./contractGraph_driver.h"
46 
47 PGDLLEXPORT Datum contractGraph(PG_FUNCTION_ARGS);
49 
50 
51 static
52 void
53 process(char* edges_sql,
54  ArrayType* order,
55  int num_cycles,
56  ArrayType* forbidden,
57 
58  bool directed,
59  pgr_contracted_blob **result_tuples,
60  size_t *result_count) {
61  /*
62  * nothing to do
63  */
64  if (num_cycles < 1) return;
65 
67 
68  size_t size_forbidden_vertices = 0;
69  int64_t* forbidden_vertices =
71  &size_forbidden_vertices,
72  forbidden);
73  PGR_DBG("size_forbidden_vertices %ld", size_forbidden_vertices);
74 
75  size_t size_contraction_order = 0;
76  int64_t* contraction_order =
78  &size_contraction_order,
79  order);
80  PGR_DBG("size_contraction_order %ld ", size_contraction_order);
81 
82 
83  size_t total_edges = 0;
84  pgr_edge_t* edges = NULL;
85  pgr_get_edges(edges_sql, &edges, &total_edges);
86  if (total_edges == 0) {
87  if (forbidden_vertices) pfree(forbidden_vertices);
88  if (contraction_order) pfree(contraction_order);
90  return;
91  }
92 
93  PGR_DBG("Starting timer");
94  clock_t start_t = clock();
95  char* log_msg = NULL;
96  char* notice_msg = NULL;
97  char* err_msg = NULL;
99  edges, total_edges,
100  forbidden_vertices, size_forbidden_vertices,
101  contraction_order, size_contraction_order,
102  num_cycles,
103  directed,
104  result_tuples, result_count,
105  &log_msg,
106  &notice_msg,
107  &err_msg);
108 
109  time_msg("processing pgr_contraction()", start_t, clock());
110 
111 
112  if (err_msg && (*result_tuples)) {
113  pfree(*result_tuples);
114  (*result_tuples) = NULL;
115  (*result_count) = 0;
116  }
117 
118  pgr_global_report(log_msg, notice_msg, err_msg);
119 
120  if (log_msg) pfree(log_msg);
121  if (notice_msg) pfree(notice_msg);
122  if (err_msg) pfree(err_msg);
123  if (edges) pfree(edges);
124  if (forbidden_vertices) pfree(forbidden_vertices);
125  if (contraction_order) pfree(contraction_order);
126  pgr_SPI_finish();
127 }
128 
129 PGDLLEXPORT Datum
130 contractGraph(PG_FUNCTION_ARGS) {
131  FuncCallContext *funcctx;
132  TupleDesc tuple_desc;
133 
134  /**********************************************************************/
135  pgr_contracted_blob *result_tuples = NULL;
136  size_t result_count = 0;
137  /**********************************************************************/
138 
139  if (SRF_IS_FIRSTCALL()) {
140  MemoryContext oldcontext;
141  funcctx = SRF_FIRSTCALL_INIT();
142  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
143  /**********************************************************************/
144  /*
145  edges_sql TEXT,
146  contraction_order BIGINT[],
147  max_cycles integer DEFAULT 1,
148  forbidden_vertices BIGINT[] DEFAULT ARRAY[]::BIGINT[],
149  directed BOOLEAN DEFAULT true,
150 
151  **********************************************************************/
152 
153  process(
154  text_to_cstring(PG_GETARG_TEXT_P(0)),
155  PG_GETARG_ARRAYTYPE_P(1),
156  PG_GETARG_INT32(2),
157  PG_GETARG_ARRAYTYPE_P(3),
158  PG_GETARG_BOOL(4),
159  &result_tuples,
160  &result_count);
161 
162 
163  /**********************************************************************/
164 #if PGSQL_VERSION > 95
165  funcctx->max_calls = result_count;
166 #else
167  funcctx->max_calls = (uint32_t)result_count;
168 #endif
169  funcctx->user_fctx = result_tuples;
170  if (get_call_result_type(fcinfo, NULL, &tuple_desc)
171  != TYPEFUNC_COMPOSITE)
172  ereport(ERROR,
173  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
174  errmsg("function returning record called in context "
175  "that cannot accept type record")));
176  funcctx->tuple_desc = tuple_desc;
177  MemoryContextSwitchTo(oldcontext);
178  }
179 
180  funcctx = SRF_PERCALL_SETUP();
181  tuple_desc = funcctx->tuple_desc;
182  result_tuples = (pgr_contracted_blob*) funcctx->user_fctx;
183 
184  if (funcctx->call_cntr < funcctx->max_calls) {
185  HeapTuple tuple;
186  Datum result;
187  Datum *values;
188  char *nulls;
189  int16 typlen;
190  size_t call_cntr = funcctx->call_cntr;
191 
192  /**********************************************************************/
193  size_t numb = 7;
194  values =(Datum *)palloc(numb * sizeof(Datum));
195  nulls = palloc(numb * sizeof(bool));
196  size_t i;
197  for (i = 0; i < numb; ++i) {
198  nulls[i] = false;
199  }
200 
201  size_t contracted_vertices_size =
202  (size_t)result_tuples[call_cntr].contracted_vertices_size;
203 
204  Datum* contracted_vertices_array;
205  contracted_vertices_array = (Datum*) palloc(sizeof(Datum) *
206  (size_t)contracted_vertices_size);
207 
208  for (i = 0; i < contracted_vertices_size; ++i) {
209  PGR_DBG("Storing contracted vertex %ld",
210  result_tuples[call_cntr].contracted_vertices[i]);
211  contracted_vertices_array[i] =
212  Int64GetDatum(result_tuples[call_cntr].contracted_vertices[i]);
213  }
214 
215  bool typbyval;
216  char typalign;
217  get_typlenbyvalalign(INT8OID, &typlen, &typbyval, &typalign);
218  ArrayType* arrayType;
219  /*
220  * https://doxygen.postgresql.org/arrayfuncs_8c.html
221 
222  ArrayType* construct_array(
223  Datum* elems,
224  int nelems,
225  Oid elmtype, int elmlen, bool elmbyval, char elmalign
226  )
227  */
228  arrayType = construct_array(
229  contracted_vertices_array,
230  (int)contracted_vertices_size,
231  INT8OID, typlen, typbyval, typalign);
232  /*
233  void TupleDescInitEntry(
234  TupleDesc desc,
235  AttrNumber attributeNumber,
236  const char * attributeName,
237  Oid oidtypeid,
238  int32 typmod,
239  int attdim
240  )
241  */
242  TupleDescInitEntry(tuple_desc, (AttrNumber) 4, "contracted_vertices",
243  INT8ARRAYOID, -1, 0);
244 
245  values[0] = Int32GetDatum(call_cntr + 1);
246  values[1] = CStringGetTextDatum(result_tuples[call_cntr].type);
247  values[2] = Int64GetDatum(result_tuples[call_cntr].id);
248  values[3] = PointerGetDatum(arrayType);
249  values[4] = Int64GetDatum(result_tuples[call_cntr].source);
250  values[5] = Int64GetDatum(result_tuples[call_cntr].target);
251  values[6] = Float8GetDatum(result_tuples[call_cntr].cost);
252 
253  /*********************************************************************/
254  tuple = heap_form_tuple(tuple_desc, values, nulls);
255  result = HeapTupleGetDatum(tuple);
256 
257  /*
258  * cleaning up the contracted vertices array
259  */
260  if (result_tuples[funcctx->call_cntr].contracted_vertices) {
261  pfree(result_tuples[funcctx->call_cntr].contracted_vertices);
262  }
263  SRF_RETURN_NEXT(funcctx, result);
264  } else {
265  SRF_RETURN_DONE(funcctx);
266  }
267 }
PGDLLEXPORT Datum contractGraph(PG_FUNCTION_ARGS)
int64_t * contracted_vertices
Definition: pgr_types.h:216
static void process(char *edges_sql, ArrayType *order, int num_cycles, ArrayType *forbidden, bool directed, pgr_contracted_blob **result_tuples, size_t *result_count)
Definition: contractGraph.c:53
#define PGR_DBG(...)
Definition: debug_macro.h:34
int64_t * pgr_get_bigIntArray_allowEmpty(size_t *arrlen, ArrayType *input)
Definition: arrays_input.c:133
void pgr_get_edges(char *edges_sql, pgr_edge_t **edges, size_t *total_edges)
basic edge_sql
Definition: edges_input.c:539
int64_t * pgr_get_bigIntArray(size_t *arrlen, ArrayType *input)
Definition: arrays_input.c:127
void time_msg(char *msg, clock_t start_t, clock_t end_t)
Definition: time_msg.c:32
PG_FUNCTION_INFO_V1(contractGraph)
void pgr_global_report(char *log, char *notice, char *err)
notice & error
Definition: e_report.c:93
void pgr_SPI_finish(void)
edge_astar_t * edges
Definition: BDATester.cpp:46
void pgr_SPI_connect(void)
#define INT8ARRAYOID
Definition: contractGraph.c:36
char * err_msg
Definition: BDATester.cpp:50
void do_pgr_contractGraph(pgr_edge_t *data_edges, size_t total_edges, int64_t *forbidden_vertices, size_t size_forbidden_vertices, int64_t *contraction_order, size_t size_contraction_order, int64_t max_cycles, bool directed, pgr_contracted_blob **return_tuples, size_t *return_count, char **log_msg, char **notice_msg, char **err_msg)