pgRouting  2.2
pgRouting extends the PostGIS / PostgreSQL geospatial database to provide geospatial routing functionality.
 All Classes Functions Variables Pages
pickDeliver/src/pdp.c
1 /*PGR-GNU*****************************************************************
2 
3 Copyright (c) 2014 Manikata Kondeti
4 mani.iiit123@gmail.com
5 
6 ------
7 
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 
22 ********************************************************************PGR-GNU*/
23 #include "postgres.h"
24 #include "executor/spi.h"
25 #include "funcapi.h"
26 #include "catalog/pg_type.h"
27 #if PGSQL_VERSION > 92
28 #include "access/htup_details.h"
29 #endif
30 
31 #include "fmgr.h"
32 #include "./pdp.h"
33 
34 
35 Datum vrppdtw(PG_FUNCTION_ARGS);
36 
37 
38 // #define DEBUG 1
39 #include "../../common/src/debug_macro.h"
40 #include "../../common/src/postgres_connection.h"
41 #include "./customers_input.h"
42 
43 
44 
45 
46 static
47 int compute_shortest_path(
48  char* sql,
49  int64_t vehicle_count,
50  double capacity,
51  path_element **results,
52  size_t *length_results_struct) {
53  PGR_DBG("start shortest_path\n");
54 
55  pgr_SPI_connect();
56  char *err_msg = NULL;
57  size_t total_customers = 0;
58  Customer *customers = NULL;
59  pgr_get_customers(sql, &customers, &total_customers);
60 
61 
62  PGR_DBG("Calling Solver Instance\n");
63 
64  int ret = Solver(customers, total_customers, vehicle_count,
65  capacity, &err_msg, results, length_results_struct);
66 
67  if (ret < -2) {
68  ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED),
69  errmsg("Error computing path: %s", err_msg)));
70  }
71 
72 
73  PGR_DBG("*length_results_count = %i\n", *length_results_struct);
74  PGR_DBG("ret = %i\n", ret);
75 
76  pfree(customers);
77  free(err_msg);
78  pgr_SPI_finish();
79  return 0;
80 }
81 
82 
83 
84 PG_FUNCTION_INFO_V1(vrppdtw);
85 Datum
86 vrppdtw(PG_FUNCTION_ARGS) {
87  FuncCallContext *funcctx;
88  int call_cntr;
89  int max_calls;
90  TupleDesc tuple_desc;
91  path_element *results = 0;
92 
93 
94  /* stuff done only on the first call of the function */
95 
96  if (SRF_IS_FIRSTCALL()) {
97  MemoryContext oldcontext;
98  size_t length_results_struct = 0;
99  funcctx = SRF_FIRSTCALL_INIT();
100  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
101  results = (path_element *)palloc(sizeof(path_element)*((length_results_struct) + 1));
102 
103  PGR_DBG("Calling compute_shortes_path");
104 
105  compute_shortest_path(
106  pgr_text2char(PG_GETARG_TEXT_P(0)), // customers sql
107  PG_GETARG_INT64(1), // vehicles count
108  PG_GETARG_FLOAT8(2), // capacity
109  &results, &length_results_struct);
110 
111  PGR_DBG("Back from solve_vrp, length_results: %d", length_results_struct);
112 
113  /* total number of tuples to be returned */
114  funcctx->max_calls = length_results_struct;
115  funcctx->user_fctx = results;
116 
117  /* Build a tuple descriptor for our result type */
118  if (get_call_result_type(fcinfo, NULL, &tuple_desc) != TYPEFUNC_COMPOSITE)
119  ereport(ERROR,
120  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
121  errmsg("function returning record called in context "
122  "that cannot accept type record")));
123 
124  funcctx->tuple_desc = BlessTupleDesc(tuple_desc);
125  MemoryContextSwitchTo(oldcontext);
126  }
127 
128  /* stuff done on every call of the function */
129  funcctx = SRF_PERCALL_SETUP();
130 
131  call_cntr = funcctx->call_cntr;
132  max_calls = funcctx->max_calls;
133  tuple_desc = funcctx->tuple_desc;
134  results = (path_element *) funcctx->user_fctx;
135 
136  /* do when there is more left to send */
137  if (call_cntr < max_calls) {
138  HeapTuple tuple;
139  Datum result;
140  Datum *values;
141  char* nulls;
142 
143  PGR_DBG("Till hereee ", NULL);
144  values = palloc(4 * sizeof(Datum));
145  nulls = palloc(4 * sizeof(char));
146 
147  nulls[0] = ' ';
148  nulls[1] = ' ';
149  nulls[2] = ' ';
150  nulls[3] = ' ';
151  values[0] = Int32GetDatum(results[call_cntr].seq);
152  values[1] = Int64GetDatum(results[call_cntr].rid);
153  values[2] = Int64GetDatum(results[call_cntr].nid);
154  values[3] = Float8GetDatum(results[call_cntr].cost);
155  tuple = heap_formtuple(tuple_desc, values, nulls);
156 
157  /* make the tuple into a datum */
158  result = HeapTupleGetDatum(tuple);
159 
160  /* clean up (this is not really necessary) */
161  pfree(values);
162  pfree(nulls);
163 
164  SRF_RETURN_NEXT(funcctx, result);
165  } else {
166  /* do when there is no more left */
167  free(results);
168  SRF_RETURN_DONE(funcctx);
169  }
170 }