/* MODIFY AS NEEDED */ static void process( char* edges_sql, ArrayType *starts, ArrayType *ends, bool directed, bool only_cost, General_path_element_t **result_tuples, size_t *result_count) { pgr_SPI_connect(); int64_t* start_vidsArr = NULL; size_t size_start_vidsArr = 0; start_vidsArr = (int64_t*) pgr_get_bigIntArray(&size_start_vidsArr, starts); int64_t* end_vidsArr = NULL; size_t size_end_vidsArr = 0; end_vidsArr = (int64_t*) pgr_get_bigIntArray(&size_end_vidsArr, ends); pgr_edge_t *edges = NULL; size_t total_edges = 0; pgr_get_edges(edges_sql, &edges, &total_edges); PGR_DBG("Total %ld edges in query:", total_edges); if (total_edges == 0) { PGR_DBG("No edges found"); pgr_SPI_finish(); return; } PGR_DBG("Starting processing"); clock_t start_t = clock(); char *log_msg = NULL; char *notice_msg = NULL; char *err_msg = NULL; do_pgr_bdDijkstra( edges, total_edges, start_vidsArr, size_start_vidsArr, end_vidsArr, size_end_vidsArr, directed, only_cost, result_tuples, result_count, &log_msg, ¬ice_msg, &err_msg); time_msg(" processing pgr_bdDijkstra", start_t, clock()); PGR_DBG("Returning %ld tuples", *result_count); if (err_msg) { if (*result_tuples) free(*result_tuples); } pgr_global_report(log_msg, notice_msg, err_msg); pfree(edges); pgr_SPI_finish(); }
Datum #else // _MSC_VER PGDLLEXPORT Datum #endif driving_many_to_dist(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; int call_cntr; int max_calls; TupleDesc tuple_desc; pgr_path_element3_t *ret_path = 0; /* stuff done only on the first call of the function */ if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; int path_count = 0; /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); /* switch to memory context appropriate for multiple function calls */ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); int64_t* sourcesArr; int num; sourcesArr = (int64_t*) pgr_get_bigIntArray(&num, PG_GETARG_ARRAYTYPE_P(1)); PGR_DBG("sourcesArr size %d ", num); PGR_DBG("Calling driving_many_to_dist_driver"); driving_many_to_dist_driver( pgr_text2char(PG_GETARG_TEXT_P(0)), // sql sourcesArr, num, // array of sources PG_GETARG_FLOAT8(2), // distance PG_GETARG_BOOL(3), // directed PG_GETARG_BOOL(4), // equicost PG_GETARG_BOOL(5), // has_rcost &ret_path, &path_count); free(sourcesArr); /* total number of tuples to be returned */ funcctx->max_calls = path_count; funcctx->user_fctx = ret_path; if (get_call_result_type(fcinfo, NULL, &tuple_desc) != TYPEFUNC_COMPOSITE) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); funcctx->tuple_desc = tuple_desc; MemoryContextSwitchTo(oldcontext); } /* stuff done on every call of the function */ funcctx = SRF_PERCALL_SETUP(); call_cntr = funcctx->call_cntr; max_calls = funcctx->max_calls; tuple_desc = funcctx->tuple_desc; ret_path = (pgr_path_element3_t*) funcctx->user_fctx; /* do when there is more left to send */ if (call_cntr < max_calls) { HeapTuple tuple; Datum result; Datum *values; char* nulls; values = palloc(6 * sizeof(Datum)); nulls = palloc(6 * sizeof(char)); // id, start_v, node, edge, cost, tot_cost values[0] = Int32GetDatum(call_cntr + 1); nulls[0] = ' '; values[1] = Int64GetDatum(ret_path[call_cntr].from); nulls[1] = ' '; values[2] = Int64GetDatum(ret_path[call_cntr].vertex); nulls[2] = ' '; values[3] = Int64GetDatum(ret_path[call_cntr].edge); nulls[3] = ' '; values[4] = Float8GetDatum(ret_path[call_cntr].cost); nulls[4] = ' '; values[5] = Float8GetDatum(ret_path[call_cntr].tot_cost); nulls[5] = ' '; tuple = heap_formtuple(tuple_desc, values, nulls); /* make the tuple into a datum */ result = HeapTupleGetDatum(tuple); /* clean up (this is not really necessary) */ pfree(values); pfree(nulls); SRF_RETURN_NEXT(funcctx, result); } else { /* do when there is no more left */ if (ret_path) free(ret_path); SRF_RETURN_DONE(funcctx); } }
Datum #else // _MSC_VER PGDLLEXPORT Datum #endif MY_FUNCTION_NAME(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; uint32_t call_cntr; uint32_t max_calls; TupleDesc tuple_desc; /**************************************************************************/ /* MODIFY AS NEEDED */ /* */ MY_RETURN_VALUE_TYPE *result_tuples = 0; size_t result_count = 0; /* */ /**************************************************************************/ if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /**********************************************************************/ /* MODIFY AS NEEDED */ /* MY_QUERY_LINE1 **********************************************************************/ PGR_DBG("Initializing arrays"); int64_t* end_vidsArr; size_t size_end_vidsArr; end_vidsArr = (int64_t*) pgr_get_bigIntArray(&size_end_vidsArr, PG_GETARG_ARRAYTYPE_P(2)); PGR_DBG("targetsArr size %ld ", size_end_vidsArr); PGR_DBG("Calling process"); // Code standard: // Use same order as in the query // Pass the array and it's size on the same line process( pgr_text2char(PG_GETARG_TEXT_P(0)), PG_GETARG_INT64(1), end_vidsArr, size_end_vidsArr, PG_GETARG_BOOL(3), &result_tuples, &result_count); // while developing leave the message as a reminder PGR_DBG("Cleaning arrays using free(<array-name>)"); free(end_vidsArr); /* */ /*******************************************************************************/ funcctx->max_calls = (uint32_t) result_count; funcctx->user_fctx = result_tuples; if (get_call_result_type(fcinfo, NULL, &tuple_desc) != TYPEFUNC_COMPOSITE) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); funcctx->tuple_desc = tuple_desc; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); call_cntr = funcctx->call_cntr; max_calls = funcctx->max_calls; tuple_desc = funcctx->tuple_desc; result_tuples = (MY_RETURN_VALUE_TYPE*) funcctx->user_fctx; if (call_cntr < max_calls) { HeapTuple tuple; Datum result; Datum *values; bool* nulls; /*******************************************************************************/ /* MODIFY!!!!! */ /* This has to match you ouput otherwise the server crashes */ /* MY_QUERY_LINE2 ********************************************************************************/ values = palloc(8 * sizeof(Datum)); nulls = palloc(8 * sizeof(bool)); size_t i; for(i = 0; i < 8; ++i) { nulls[i] = false; } // postgres starts counting from 1 values[0] = Int32GetDatum(call_cntr + 1); values[1] = Int32GetDatum(result_tuples[call_cntr].seq); values[2] = Int64GetDatum(result_tuples[call_cntr].start_id); values[3] = Int64GetDatum(result_tuples[call_cntr].end_id); values[4] = Int64GetDatum(result_tuples[call_cntr].node); values[5] = Int64GetDatum(result_tuples[call_cntr].edge); values[6] = Float8GetDatum(result_tuples[call_cntr].cost); values[7] = Float8GetDatum(result_tuples[call_cntr].agg_cost); /*******************************************************************************/ tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } else { // cleanup if (result_tuples) free(result_tuples); SRF_RETURN_DONE(funcctx); } }
Datum #else // _MSC_VER PGDLLEXPORT Datum #endif many_to_one_dijkstra(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; uint32_t call_cntr; uint32_t max_calls; TupleDesc tuple_desc; /**************************************************************************/ /* MODIFY AS NEEDED */ /* */ General_path_element_t *result_tuples = 0; size_t result_count = 0; /* */ /**************************************************************************/ if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /*********************************************************************/ /* MODIFY AS NEEDED */ // CREATE OR REPLACE FUNCTION pgr_dijkstra( // sql text, // start_vids anyarray, // end_vid BIGINT, // directed BOOLEAN default true, PGR_DBG("Initializing arrays"); int64_t* start_vidsArr; size_t size_start_vidsArr; start_vidsArr = (int64_t*) pgr_get_bigIntArray(&size_start_vidsArr, PG_GETARG_ARRAYTYPE_P(1)); PGR_DBG("start_vidsArr size %ld ", size_start_vidsArr); PGR_DBG("Calling process"); process( pgr_text2char(PG_GETARG_TEXT_P(0)), start_vidsArr, size_start_vidsArr, PG_GETARG_INT64(2), PG_GETARG_BOOL(3), PG_GETARG_BOOL(4), &result_tuples, &result_count); PGR_DBG("Cleaning arrays"); free(start_vidsArr); /* */ /*********************************************************************/ funcctx->max_calls = (uint32_t) result_count; funcctx->user_fctx = result_tuples; if (get_call_result_type(fcinfo, NULL, &tuple_desc) != TYPEFUNC_COMPOSITE) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); } funcctx->tuple_desc = tuple_desc; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); call_cntr = funcctx->call_cntr; max_calls = funcctx->max_calls; tuple_desc = funcctx->tuple_desc; result_tuples = (General_path_element_t*) funcctx->user_fctx; if (call_cntr < max_calls) { HeapTuple tuple; Datum result; Datum *values; bool* nulls; /*********************************************************************/ /* MODIFY AS NEEDED */ // OUT seq INTEGER, // OUT path_seq INTEGER, // OUT start_vid BIGINT, // OUT end_vid BIGINT, // OUT node BIGINT, // OUT edge BIGINT, // OUT cost FLOAT, // OUT agg_cost FLOAT) values = palloc(7 * sizeof(Datum)); nulls = palloc(7 * sizeof(bool)); size_t i; for (i = 0; i < 7; ++i) { nulls[i] = false; } // postgres starts counting from 1 values[0] = Int32GetDatum(call_cntr + 1); values[1] = Int32GetDatum(result_tuples[call_cntr].seq); values[2] = Int64GetDatum(result_tuples[call_cntr].start_id); values[3] = Int64GetDatum(result_tuples[call_cntr].node); values[4] = Int64GetDatum(result_tuples[call_cntr].edge); values[5] = Float8GetDatum(result_tuples[call_cntr].cost); values[6] = Float8GetDatum(result_tuples[call_cntr].agg_cost); /*********************************************************************/ tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } else { // cleanup if (result_tuples) free(result_tuples); SRF_RETURN_DONE(funcctx); } }
/* MODIFY AS NEEDED */ static void process( char* edges_sql, int64_t start_vid, int64_t end_vid, #if 0 /* * handling arrays example */ ArrayType *starts, ArrayType *ends, #endif bool directed, bool only_cost, MY_RETURN_VALUE_TYPE **result_tuples, size_t *result_count) { /* * https://www.postgresql.org/docs/current/static/spi-spi-connect.html */ pgr_SPI_connect(); #if 0 /* * handling arrays example */ PGR_DBG("Initializing arrays"); int64_t* start_vidsArr = NULL; size_t size_start_vidsArr = 0; start_vidsArr = (int64_t*) pgr_get_bigIntArray(&size_start_vidsArr, starts); PGR_DBG("start_vidsArr size %ld ", size_start_vidsArr); int64_t* end_vidsArr = NULL; size_t size_end_vidsArr = 0; end_vidsArr = (int64_t*) pgr_get_bigIntArray(&size_end_vidsArr, ends); PGR_DBG("end_vidsArr size %ld ", size_end_vidsArr); #endif (*result_tuples) = NULL; (*result_count) = 0; PGR_DBG("Load data"); MY_EDGE_TYPE *edges = NULL; size_t total_edges = 0; if (start_vid == end_vid) { /* * https://www.postgresql.org/docs/current/static/spi-spi-finish.html */ pgr_SPI_finish(); return; } MY_EDGE_FUNCTION(edges_sql, &edges, &total_edges); PGR_DBG("Total %ld edges in query:", total_edges); if (total_edges == 0) { PGR_DBG("No edges found"); pgr_SPI_finish(); return; } PGR_DBG("Starting processing"); clock_t start_t = clock(); char *log_msg = NULL; char *notice_msg = NULL; char *err_msg = NULL; do_pgr_MY_FUNCTION_NAME( edges, total_edges, start_vid, end_vid, #if 0 /* * handling arrays example */ start_vidsArr, size_start_vidsArr, end_vidsArr, size_end_vidsArr, #endif directed, only_cost, result_tuples, result_count, &log_msg, ¬ice_msg, &err_msg); time_msg(" processing pgr_MY_FUNCTION_NAME", start_t, clock()); PGR_DBG("Returning %ld tuples", *result_count); if (err_msg) { if (*result_tuples) pfree(*result_tuples); } pgr_global_report(log_msg, notice_msg, err_msg); if (edges) pfree(edges); if (log_msg) pfree(log_msg); if (notice_msg) pfree(notice_msg); if (err_msg) pfree(err_msg); #if 0 /* * handling arrays example */ if (end_vidsArr) pfree(end_vidsArr); if (start_vidsArr) pfree(start_vidsArr); #endif pgr_SPI_finish(); }
static void process( char *edges_sql, ArrayType *starts, ArrayType *ends, char *algorithm, bool only_flow, pgr_flow_t **result_tuples, size_t *result_count) { if (!(strcmp(algorithm, "push_relabel") == 0 || strcmp(algorithm, "edmonds_karp") == 0 || strcmp(algorithm, "boykov_kolmogorov") == 0)) { elog(ERROR, "Unknown algorithm"); } pgr_SPI_connect(); size_t size_source_verticesArr = 0; int64_t* source_vertices = pgr_get_bigIntArray(&size_source_verticesArr, starts); size_t size_sink_verticesArr = 0; int64_t* sink_vertices = pgr_get_bigIntArray(&size_sink_verticesArr, ends); pgr_edge_t *edges = NULL; size_t total_edges = 0; /* NOTE: * For flow, cost and reverse_cost are really capacity and reverse_capacity */ pgr_get_flow_edges(edges_sql, &edges, &total_edges); if (total_edges == 0) { if (source_vertices) pfree(source_vertices); if (sink_vertices) pfree(sink_vertices); pgr_SPI_finish(); return; } PGR_DBG("Starting timer"); clock_t start_t = clock(); char* log_msg = NULL; char* notice_msg = NULL; char *err_msg = NULL; do_pgr_max_flow( edges, total_edges, source_vertices, size_source_verticesArr, sink_vertices, size_sink_verticesArr, algorithm, only_flow, result_tuples, result_count, &log_msg, ¬ice_msg, &err_msg); if (only_flow) { time_msg("pgr_maxFlow(many to many)", start_t, clock()); } else if (strcmp(algorithm, "push_relabel") == 0) { time_msg("pgr_maxFlowPushRelabel(many to many)", start_t, clock()); } else if (strcmp(algorithm, "edmonds_karp") == 0) { time_msg("pgr_maxFlowEdmondsKarp(many to many)", start_t, clock()); } else { time_msg("pgr_maxFlowBoykovKolmogorov(many to many)", start_t, clock()); } if (edges) pfree(edges); if (source_vertices) pfree(source_vertices); if (sink_vertices) pfree(sink_vertices); if (err_msg && (*result_tuples)) { pfree(*result_tuples); (*result_tuples) = NULL; (*result_count) = 0; } pgr_global_report(log_msg, notice_msg, err_msg); if (log_msg) pfree(log_msg); if (notice_msg) pfree(notice_msg); if (err_msg) pfree(err_msg); pgr_SPI_finish(); }
static void process( char* edges_sql, char* points_sql, int64_t start_pid, ArrayType *ends, bool directed, char *driving_side, bool details, bool only_cost, General_path_element_t **result_tuples, size_t *result_count) { driving_side[0] = estimate_drivingSide(driving_side[0]); PGR_DBG("estimated driving side:%c", driving_side[0]); pgr_SPI_connect(); size_t size_end_pidsArr = 0; int64_t* end_pidsArr = pgr_get_bigIntArray(&size_end_pidsArr, ends); PGR_DBG("load the points"); size_t total_points = 0; Point_on_edge_t *points = NULL; pgr_get_points(points_sql, &points, &total_points); PGR_DBG(" -- change the query"); char *edges_of_points_query = NULL; char *edges_no_points_query = NULL; get_new_queries( edges_sql, points_sql, &edges_of_points_query, &edges_no_points_query); PGR_DBG("edges_of_points_query:\n%s", edges_of_points_query); PGR_DBG("edges_no_points_query:\n%s", edges_no_points_query); PGR_DBG("load the edges that match the points"); pgr_edge_t *edges_of_points = NULL; size_t total_edges_of_points = 0; pgr_get_edges( edges_of_points_query, &edges_of_points, &total_edges_of_points); PGR_DBG("Total %ld edges in query:", total_edges_of_points); PGR_DBG("load the edges that don't match the points"); pgr_edge_t *edges = NULL; size_t total_edges = 0; pgr_get_edges(edges_no_points_query, &edges, &total_edges); PGR_DBG("Total %ld edges in query:", total_edges); free(edges_of_points_query); free(edges_no_points_query); if ((total_edges + total_edges_of_points) == 0) { PGR_DBG("No edges found"); pgr_SPI_finish(); return; } PGR_DBG("Starting timer"); clock_t start_t = clock(); char* log_msg = NULL; char* notice_msg = NULL; char* err_msg = NULL; do_pgr_many_to_many_withPoints( edges, total_edges, points, total_points, edges_of_points, total_edges_of_points, &start_pid, 1, end_pidsArr, size_end_pidsArr, driving_side[0], details, directed, only_cost, true, result_tuples, result_count, &log_msg, ¬ice_msg, &err_msg); if (only_cost) { time_msg("processing pgr_withPointsCost(one to many)", start_t, clock()); } else { time_msg("processing pgr_withPoints(one to many)", start_t, clock()); } if (err_msg && (*result_tuples)) { pfree(*result_tuples); (*result_count) = 0; (*result_tuples) = NULL; } pgr_global_report(log_msg, notice_msg, err_msg); if (log_msg) pfree(log_msg); if (notice_msg) pfree(notice_msg); if (err_msg) pfree(err_msg); if (edges) pfree(edges); if (points) pfree(points); if (edges_of_points) pfree(edges_of_points); if (end_pidsArr) pfree(end_pidsArr); pgr_SPI_finish(); }
PGDLLEXPORT Datum edge_disjoint_paths_many_to_one(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; uint32_t call_cntr; uint32_t max_calls; TupleDesc tuple_desc; /**************************************************************************/ /* MODIFY AS NEEDED */ /* */ General_path_element_t *result_tuples = 0; size_t result_count = 0; /* */ /**************************************************************************/ if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /**********************************************************************/ /* MODIFY AS NEEDED */ int64_t *source_vertices; size_t size_source_verticesArr; source_vertices = (int64_t *) pgr_get_bigIntArray(&size_source_verticesArr, PG_GETARG_ARRAYTYPE_P(1)); PGR_DBG("source_verticesArr size %ld ", size_source_verticesArr); PGR_DBG("Calling process"); process( pgr_text2char(PG_GETARG_TEXT_P(0)), source_vertices, size_source_verticesArr, PG_GETARG_INT64(2), PG_GETARG_BOOL(3), &result_tuples, &result_count); free(source_vertices); /* */ /**********************************************************************/ funcctx->max_calls = (uint32_t) result_count; funcctx->user_fctx = result_tuples; if (get_call_result_type(fcinfo, NULL, &tuple_desc) != TYPEFUNC_COMPOSITE) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); } funcctx->tuple_desc = tuple_desc; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); call_cntr = (uint32_t)funcctx->call_cntr; max_calls = (uint32_t)funcctx->max_calls; tuple_desc = funcctx->tuple_desc; result_tuples = (General_path_element_t *) funcctx->user_fctx; if (call_cntr < max_calls) { HeapTuple tuple; Datum result; Datum *values; bool *nulls; /**********************************************************************/ /* MODIFY AS NEEDED */ values = palloc(5 * sizeof(Datum)); nulls = palloc(5 * sizeof(bool)); size_t i; for (i = 0; i < 5; ++i) { nulls[i] = false; } // postgres starts counting from 1 values[0] = Int32GetDatum(call_cntr + 1); values[1] = Int32GetDatum(result_tuples[call_cntr].seq); values[2] = Int64GetDatum(result_tuples[call_cntr].start_id); values[3] = Int64GetDatum(result_tuples[call_cntr].node); values[4] = Int64GetDatum(result_tuples[call_cntr].edge); /**********************************************************************/ tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } else { // cleanup if (result_tuples) free(result_tuples); SRF_RETURN_DONE(funcctx); } }
static void process( char* edges_sql, char* points_sql, ArrayType *starts, ArrayType *ends, bool directed, char *driving_side, bool details, bool only_cost, General_path_element_t **result_tuples, size_t *result_count) { driving_side[0] = estimate_drivingSide(driving_side[0]); pgr_SPI_connect(); size_t size_start_pidsArr = 0; int64_t* start_pidsArr = pgr_get_bigIntArray(&size_start_pidsArr, starts); size_t size_end_pidsArr = 0; int64_t* end_pidsArr = pgr_get_bigIntArray(&size_end_pidsArr, ends); Point_on_edge_t *points = NULL; size_t total_points = 0; pgr_get_points(points_sql, &points, &total_points); char *edges_of_points_query = NULL; char *edges_no_points_query = NULL; get_new_queries( edges_sql, points_sql, &edges_of_points_query, &edges_no_points_query); pgr_edge_t *edges_of_points = NULL; size_t total_edges_of_points = 0; pgr_get_edges( edges_of_points_query, &edges_of_points, &total_edges_of_points); pgr_edge_t *edges = NULL; size_t total_edges = 0; pgr_get_edges(edges_no_points_query, &edges, &total_edges); free(edges_of_points_query); free(edges_no_points_query); if ((total_edges + total_edges_of_points) == 0) { pgr_SPI_finish(); return; } clock_t start_t = clock(); char* log_msg = NULL; char* notice_msg = NULL; char* err_msg = NULL; do_pgr_many_to_many_withPoints( edges, total_edges, points, total_points, edges_of_points, total_edges_of_points, start_pidsArr, size_start_pidsArr, end_pidsArr, size_end_pidsArr, driving_side[0], details, directed, only_cost, true, result_tuples, result_count, &log_msg, ¬ice_msg, &err_msg); if (only_cost) { time_msg("processing pgr_withPointsCost(one to one)", start_t, clock()); } else { time_msg("processing pgr_withPoints(one to one)", start_t, clock()); } if (err_msg && (*result_tuples)) { pfree(*result_tuples); (*result_count) = 0; (*result_tuples) = NULL; } pgr_global_report(log_msg, notice_msg, err_msg); #if 0 if (log_msg) pfree(log_msg); if (notice_msg) pfree(notice_msg); if (err_msg) pfree(err_msg); if (edges) pfree(edges); if (points) pfree(points); if (edges_of_points) pfree(edges_of_points); if (start_pidsArr) pfree(start_pidsArr); if (end_pidsArr) pfree(end_pidsArr); #endif pgr_SPI_finish(); }