31 #include "executor/spi.h"
33 #include "utils/array.h"
34 #include "catalog/pg_type.h"
35 #if PGSQL_VERSION > 92
36 #include "access/htup_details.h"
41 #include "./../../common/src/debug_macro.h"
42 #include "./../../common/src/time_msg.h"
43 #include "./../../common/src/pgr_types.h"
44 #include "./../../common/src/postgres_connection.h"
45 #include "./../../common/src/edges_input.h"
46 #include "./../../common/src/arrays_input.h"
47 #include "./../../common/src/points_input.h"
63 size_t size_end_pidsArr,
69 size_t *result_count) {
70 driving_side[0] = (char) tolower(driving_side[0]);
71 PGR_DBG(
"driving side:%c", driving_side[0]);
72 if (!((driving_side[0] ==
'r')
73 || (driving_side[0] ==
'l'))) {
74 driving_side[0] =
'b';
76 PGR_DBG(
"estimated driving side:%c", driving_side[0]);
81 size_t total_points = 0;
87 for (i = 0; i < total_points; i ++) {
88 PGR_DBG(
"%ld\t%ld\t%f\t%c", points[i].pid, points[i].edge_id, points[i].fraction, points[i].side);
95 PGR_DBG(
" -- change the query");
96 char *edges_of_points_query = NULL;
97 char *edges_no_points_query = NULL;
99 edges_sql, points_sql,
100 &edges_of_points_query,
101 &edges_no_points_query);
103 PGR_DBG(
"edges_of_points_query:\n%s", edges_of_points_query);
104 PGR_DBG(
"edges_no_points_query:\n%s", edges_no_points_query);
106 PGR_DBG(
"load the edges that match the points");
108 size_t total_edges_of_points = 0;
109 pgr_get_edges(edges_of_points_query, &edges_of_points, &total_edges_of_points);
111 PGR_DBG(
"Total %ld edges in query:", total_edges_of_points);
114 for (i = 0; i < total_edges_of_points; i ++) {
115 PGR_DBG(
"%ld\t%ld\t%ld\t%f\t%f",
116 edges_of_points[i].
id,
117 edges_of_points[i].source,
118 edges_of_points[i].target,
119 edges_of_points[i].cost,
120 edges_of_points[i].reverse_cost);
126 PGR_DBG(
"load the edges that don't match the points");
128 size_t total_edges = 0;
131 PGR_DBG(
"Total %ld edges in query:", total_edges);
134 for (i = 0; i < total_edges; i ++) {
135 PGR_DBG(
"%ld\t%ld\t%ld\t%f\t%f",
140 edges[i].reverse_cost);
143 PGR_DBG(
"freeing allocated memory not used anymore");
145 free(edges_of_points_query);
146 free(edges_no_points_query);
148 if ((total_edges + total_edges_of_points) == 0) {
151 (*result_tuples) = NULL;
156 PGR_DBG(
"Starting processing");
158 char *log_msg = NULL;
159 clock_t start_t = clock();
162 points, total_points,
163 edges_of_points, total_edges_of_points,
165 end_pidsArr, size_end_pidsArr,
174 time_msg(
" processing withPoints one to many", start_t, clock());
175 PGR_DBG(
"Returning %ld tuples\n", *result_count);
178 if (log_msg) free(log_msg);
181 if (*result_tuples) free(*result_tuples);
182 if (end_pidsArr) free(end_pidsArr);
183 elog(ERROR,
"%s", err_msg);
196 FuncCallContext *funcctx;
199 TupleDesc tuple_desc;
205 size_t result_count = 0;
209 if (SRF_IS_FIRSTCALL()) {
210 MemoryContext oldcontext;
211 funcctx = SRF_FIRSTCALL_INIT();
212 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
228 PGR_DBG(
"Initializing arrays");
229 int64_t* end_pidsArr;
230 size_t size_end_pidsArr;
231 end_pidsArr = (int64_t*)
238 end_pidsArr, size_end_pidsArr,
251 funcctx->max_calls = (uint32_t)result_count;
252 funcctx->user_fctx = result_tuples;
253 if (get_call_result_type(fcinfo, NULL, &tuple_desc) != TYPEFUNC_COMPOSITE)
255 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
256 errmsg(
"function returning record called in context "
257 "that cannot accept type record")));
259 funcctx->tuple_desc = tuple_desc;
260 MemoryContextSwitchTo(oldcontext);
263 funcctx = SRF_PERCALL_SETUP();
264 call_cntr = funcctx->call_cntr;
265 max_calls = funcctx->max_calls;
266 tuple_desc = funcctx->tuple_desc;
269 if (call_cntr < max_calls) {
285 values = palloc(7 *
sizeof(Datum));
286 nulls = palloc(7 *
sizeof(
bool));
289 for (i = 0; i < 7; ++i) {
295 values[0] = Int32GetDatum(call_cntr + 1);
296 values[1] = Int32GetDatum(result_tuples[call_cntr].seq);
297 values[2] = Int64GetDatum(result_tuples[call_cntr].end_id);
298 values[3] = Int64GetDatum(result_tuples[call_cntr].node);
299 values[4] = Int64GetDatum(result_tuples[call_cntr].
edge);
300 values[5] = Float8GetDatum(result_tuples[call_cntr].cost);
301 values[6] = Float8GetDatum(result_tuples[call_cntr].agg_cost);
304 tuple = heap_form_tuple(tuple_desc, values, nulls);
305 result = HeapTupleGetDatum(tuple);
306 SRF_RETURN_NEXT(funcctx, result);
309 if (result_tuples) free(result_tuples);
311 SRF_RETURN_DONE(funcctx);
static void process(char *edges_sql, char *points_sql, int64_t start_pid, int64_t *end_pidsArr, size_t size_end_pidsArr, bool directed, char *driving_side, bool details, bool only_cost, General_path_element_t **result_tuples, size_t *result_count)
void time_msg(char *msg, clock_t start_t, clock_t end_t)
void pgr_SPI_finish(void)
void get_new_queries(char *edges_sql, char *points_sql, char **edges_of_points_query, char **edges_no_points_query)
void pgr_SPI_connect(void)
PGDLLEXPORT Datum one_to_many_withPoints(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(one_to_many_withPoints)
char * pgr_text2char(text *in)
void do_pgr_one_to_many_withPoints(pgr_edge_t *edges, size_t total_edges, Point_on_edge_t *points_p, size_t total_points, pgr_edge_t *edges_of_points, size_t total_edges_of_points, int64_t start_vid, int64_t *end_pidsArr, size_t size_end_pidsArr, char driving_side, bool details, bool directed, bool only_cost, General_path_element_t **return_tuples, size_t *return_count, char **log_msg, char **err_msg)