PGROUTING  3.2
minCostMaxFlow.c File Reference

Connecting code with postgres. More...

#include <stdbool.h>
#include "c_common/postgres_connection.h"
#include "utils/array.h"
#include "c_common/debug_macro.h"
#include "c_common/e_report.h"
#include "c_common/time_msg.h"
#include "c_common/edges_input.h"
#include "c_common/arrays_input.h"
#include "c_common/combinations_input.h"
#include "drivers/max_flow/minCostMaxFlow_driver.h"
Include dependency graph for minCostMaxFlow.c:

Go to the source code of this file.

Functions

PGDLLEXPORT Datum _pgr_maxflowmincost (PG_FUNCTION_ARGS)
 postgres_connection.h More...
 
 PG_FUNCTION_INFO_V1 (_pgr_maxflowmincost)
 
static void process (char *edges_sql, char *combinations_sql, ArrayType *starts, ArrayType *ends, bool only_cost, pgr_flow_t **result_tuples, size_t *result_count)
 

Detailed Description

Connecting code with postgres.

This file is fully documented for understanding how the postgres connectinon works

TODO Remove unnecessary comments before submiting the function. some comments are in form of PGR_DBG message

Definition in file minCostMaxFlow.c.

Function Documentation

◆ _pgr_maxflowmincost()

PGDLLEXPORT Datum _pgr_maxflowmincost ( PG_FUNCTION_ARGS  )

postgres_connection.h

  • should always be first in the C code

Definition at line 178 of file minCostMaxFlow.c.

178  {
179  FuncCallContext *funcctx;
180  TupleDesc tuple_desc;
181 
182  /**************************************************************************/
183  /* MODIFY AS NEEDED */
184  /* */
185  pgr_flow_t *result_tuples = NULL;
186  size_t result_count = 0;
187  /* */
188  /**************************************************************************/
189 
190  if (SRF_IS_FIRSTCALL()) {
191  MemoryContext oldcontext;
192  funcctx = SRF_FIRSTCALL_INIT();
193  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
194 
195 
196  /**********************************************************************/
197  /* MODIFY AS NEEDED */
198  /*
199  TEXT,
200  BIGINT,
201  BIGINT,
202  **********************************************************************/
203 
204 
205  PGR_DBG("Calling process");
206 
207  if (PG_NARGS() == 4) {
208  /*
209  * many to many
210  */
211  process(
212  text_to_cstring(PG_GETARG_TEXT_P(0)),
213  NULL,
214  PG_GETARG_ARRAYTYPE_P(1),
215  PG_GETARG_ARRAYTYPE_P(2),
216  PG_GETARG_BOOL(3),
217  &result_tuples,
218  &result_count);
219 
220  } else if (PG_NARGS() == 3) {
221  /*
222  * combinations
223  */
224  process(
225  text_to_cstring(PG_GETARG_TEXT_P(0)),
226  text_to_cstring(PG_GETARG_TEXT_P(1)),
227  NULL,
228  NULL,
229  PG_GETARG_BOOL(2),
230  &result_tuples,
231  &result_count);
232  }
233 
234  /* */
235  /**********************************************************************/
236 
237 #if PGSQL_VERSION > 94
238  funcctx->max_calls = (uint32_t)result_count;
239 #else
240  funcctx->max_calls = (uint32_t)result_count;
241 #endif
242  funcctx->user_fctx = result_tuples;
243  if (get_call_result_type(fcinfo, NULL, &tuple_desc)
244  != TYPEFUNC_COMPOSITE) {
245  ereport(ERROR,
246  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
247  errmsg("function returning record called in context "
248  "that cannot accept type record")));
249  }
250 
251  funcctx->tuple_desc = tuple_desc;
252  MemoryContextSwitchTo(oldcontext);
253  }
254 
255  funcctx = SRF_PERCALL_SETUP();
256  tuple_desc = funcctx->tuple_desc;
257  result_tuples = (pgr_flow_t*) funcctx->user_fctx;
258 
259  if (funcctx->call_cntr < funcctx->max_calls) {
260  HeapTuple tuple;
261  Datum result;
262  Datum *values;
263  bool* nulls;
264 
265  /**********************************************************************/
266  /* MODIFY AS NEEDED */
267  /*
268  ***********************************************************************/
269 
270  values = palloc(8 * sizeof(Datum));
271  nulls = palloc(8 * sizeof(bool));
272 
273 
274  size_t i;
275  for (i = 0; i < 8; ++i) {
276  nulls[i] = false;
277  }
278 
279  // postgres starts counting from 1
280  values[0] = Int32GetDatum(funcctx->call_cntr + 1);
281  values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr].edge);
282  values[2] = Int64GetDatum(result_tuples[funcctx->call_cntr].source);
283  values[3] = Int64GetDatum(result_tuples[funcctx->call_cntr].target);
284  values[4] = Int64GetDatum(result_tuples[funcctx->call_cntr].flow);
285  values[5] = Int64GetDatum(
286  result_tuples[funcctx->call_cntr].residual_capacity);
287  values[6] = Float8GetDatum(result_tuples[funcctx->call_cntr].cost);
288  values[7] = Float8GetDatum(result_tuples[funcctx->call_cntr].agg_cost);
289  /**********************************************************************/
290 
291  tuple = heap_form_tuple(tuple_desc, values, nulls);
292  result = HeapTupleGetDatum(tuple);
293  SRF_RETURN_NEXT(funcctx, result);
294  } else {
295  /**********************************************************************/
296  /* MODIFY AS NEEDED */
297 
298  PGR_DBG("Clean up code");
299 
300  /**********************************************************************/
301 
302  SRF_RETURN_DONE(funcctx);
303  }
304 }

References pgr_flow_t::agg_cost, pgr_flow_t::cost, pgr_flow_t::edge, pgr_flow_t::flow, if(), PGR_DBG, process(), pgr_flow_t::residual_capacity, pgr_flow_t::source, and pgr_flow_t::target.

◆ PG_FUNCTION_INFO_V1()

PG_FUNCTION_INFO_V1 ( _pgr_maxflowmincost  )

◆ process()

static void process ( char *  edges_sql,
char *  combinations_sql,
ArrayType *  starts,
ArrayType *  ends,
bool  only_cost,
pgr_flow_t **  result_tuples,
size_t *  result_count 
)
static

Definition at line 73 of file minCostMaxFlow.c.

80  {
81  /*
82  * https://www.postgresql.org/docs/current/static/spi-spi-connect.html
83  */
85 
86  int64_t *sourceVertices = NULL;
87  size_t sizeSourceVerticesArr = 0;
88 
89  int64_t *sinkVertices = NULL;
90  size_t sizeSinkVerticesArr = 0;
91 
92  PGR_DBG("Load data");
93  pgr_costFlow_t *edges = NULL;
94  size_t total_edges = 0;
95 
96  pgr_combination_t *combinations = NULL;
97  size_t total_combinations = 0;
98 
99  if (starts && ends) {
100  sourceVertices = (int64_t*)
101  pgr_get_bigIntArray(&sizeSourceVerticesArr, starts);
102  sinkVertices = (int64_t*)
103  pgr_get_bigIntArray(&sizeSinkVerticesArr, ends);
104  } else if (combinations_sql) {
105  pgr_get_combinations(combinations_sql, &combinations, &total_combinations);
106  if (total_combinations == 0) {
107  if (combinations)
108  pfree(combinations);
109  pgr_SPI_finish();
110  return;
111  }
112  }
113 
114  pgr_get_costFlow_edges(edges_sql, &edges, &total_edges);
115  PGR_DBG("Total %ld edges in query:", total_edges);
116 
117  if (total_edges == 0) {
118  if (sourceVertices)
119  pfree(sourceVertices);
120  if (sinkVertices)
121  pfree(sinkVertices);
122  PGR_DBG("No edges found");
123  pgr_SPI_finish();
124  return;
125  }
126 
127  PGR_DBG("Starting processing");
128  clock_t start_t = clock();
129  char *log_msg = NULL;
130  char *notice_msg = NULL;
131  char *err_msg = NULL;
132 
134  edges, total_edges,
135  combinations, total_combinations,
136  sourceVertices, sizeSourceVerticesArr,
137  sinkVertices, sizeSinkVerticesArr,
138  only_cost,
139 
140  result_tuples, result_count,
141 
142  &log_msg,
143  &notice_msg,
144  &err_msg);
145 
146  if (only_cost) {
147  time_msg(" processing pgr_minCostMaxFlow_Cost", start_t, clock());
148  } else {
149  time_msg(" processing pgr_minCostMaxFlow", start_t, clock());
150  }
151 
152  PGR_DBG("Returning %ld tuples", *result_count);
153 
154  if (edges)
155  pfree(edges);
156  if (sourceVertices)
157  pfree(sourceVertices);
158  if (sinkVertices)
159  pfree(sinkVertices);
160 
161  if (err_msg && (*result_tuples)) {
162  pfree(*result_tuples);
163  (*result_tuples) = NULL;
164  (*result_count) = 0;
165  }
166 
167  pgr_global_report(log_msg, notice_msg, err_msg);
168 
169  if (log_msg) pfree(log_msg);
170  if (notice_msg) pfree(notice_msg);
171  if (err_msg) pfree(err_msg);
172 
173  pgr_SPI_finish();
174 }

References do_pgr_minCostMaxFlow(), PGR_DBG, pgr_get_bigIntArray(), pgr_get_combinations(), pgr_get_costFlow_edges(), pgr_global_report(), pgr_SPI_connect(), pgr_SPI_finish(), and time_msg().

Referenced by _pgr_maxflowmincost().

pgr_SPI_connect
void pgr_SPI_connect(void)
Definition: postgres_connection.c:82
pgr_SPI_finish
void pgr_SPI_finish(void)
Definition: postgres_connection.c:71
process
static void process(char *edges_sql, char *combinations_sql, ArrayType *starts, ArrayType *ends, bool only_cost, pgr_flow_t **result_tuples, size_t *result_count)
Definition: minCostMaxFlow.c:73
pgr_flow_t
Definition: pgr_flow_t.h:37
pgr_get_bigIntArray
int64_t * pgr_get_bigIntArray(size_t *arrlen, ArrayType *input)
Enforces the input array to be NOT empty.
Definition: arrays_input.c:146
PGR_DBG
#define PGR_DBG(...)
Definition: debug_macro.h:34
pgr_combination_t
Definition: pgr_combination_t.h:43
pgr_get_combinations
void pgr_get_combinations(char *combinations_sql, pgr_combination_t **combinations, size_t *total_combinations)
combinations_sql
Definition: combinations_input.c:147
pgr_get_costFlow_edges
void pgr_get_costFlow_edges(char *sql, pgr_costFlow_t **edges, size_t *total_edges)
read edges for cost flow
Definition: edges_input.c:701
if
if(DOXYGEN_FOUND) configure_file($
Definition: doxygen/CMakeLists.txt:13
time_msg
void time_msg(char *msg, clock_t start_t, clock_t end_t)
Definition: time_msg.c:32
pgr_costFlow_t
Definition: pgr_costFlow_t.h:38
do_pgr_minCostMaxFlow
void do_pgr_minCostMaxFlow(pgr_costFlow_t *data_edges, size_t total_edges, pgr_combination_t *combinations, size_t total_combinations, int64_t *sourceVertices, size_t sizeSourceVerticesArr, int64_t *sinkVertices, size_t sizeSinkVerticesArr, bool only_cost, pgr_flow_t **return_tuples, size_t *return_count, char **log_msg, char **notice_msg, char **err_msg)
Definition: minCostMaxFlow_driver.cpp:43
pgr_global_report
void pgr_global_report(char *log, char *notice, char *err)
notice & error
Definition: e_report.c:93