31 #include "utils/array.h"
42 PGDLLEXPORT Datum
_pgr_tsp(PG_FUNCTION_ARGS);
55 int64_t tries_per_temperature,
56 int64_t max_changes_per_temperature,
57 int64_t max_consecutive_non_changes,
59 double initial_temperature,
60 double final_temperature,
61 double cooling_factor,
66 size_t *result_count) {
73 if (initial_temperature < final_temperature) {
74 elog(ERROR,
"Condition not met: initial_temperature"
75 " > final_temperature");
77 if (final_temperature <= 0) {
78 elog(ERROR,
"Condition not met: final_temperature > 0");
80 if (cooling_factor <=0 || cooling_factor >=1) {
81 elog(ERROR,
"Condition not met: 0 < cooling_factor < 1");
83 if (tries_per_temperature < 0) {
84 elog(ERROR,
"Condition not met: tries_per_temperature >= 0");
86 if (max_changes_per_temperature < 1) {
87 elog(ERROR,
"Condition not met: max_changes_per_temperature > 0");
89 if (max_consecutive_non_changes < 1) {
90 elog(ERROR,
"Condition not met: max_consecutive_non_changes > 0");
93 elog(ERROR,
"Condition not met: max_processing_time >= 0");
98 size_t total_distances = 0;
101 if (total_distances == 0) {
104 (*result_tuples) = NULL;
111 clock_t start_t = clock();
112 char* log_msg = NULL;
113 char* notice_msg = NULL;
114 char* err_msg = NULL;
117 distances, total_distances,
123 tries_per_temperature,
124 max_changes_per_temperature,
125 max_consecutive_non_changes,
136 if (err_msg && (*result_tuples)) {
137 pfree(*result_tuples);
138 (*result_tuples) = NULL;
144 if (log_msg) pfree(log_msg);
145 if (notice_msg) pfree(notice_msg);
146 if (err_msg) pfree(err_msg);
147 if (distances) pfree(distances);
157 FuncCallContext *funcctx;
158 TupleDesc tuple_desc;
164 size_t result_count = 0;
168 if (SRF_IS_FIRSTCALL()) {
169 MemoryContext oldcontext;
170 funcctx = SRF_FIRSTCALL_INIT();
171 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
197 text_to_cstring(PG_GETARG_TEXT_P(0)),
217 #if PGSQL_VERSION > 95
218 funcctx->max_calls = result_count;
220 funcctx->max_calls = (uint32_t)result_count;
223 funcctx->user_fctx = result_tuples;
224 if (get_call_result_type(fcinfo, NULL, &tuple_desc)
225 != TYPEFUNC_COMPOSITE) {
227 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
228 errmsg(
"function returning record called in context "
229 "that cannot accept type record")));
232 funcctx->tuple_desc = tuple_desc;
233 MemoryContextSwitchTo(oldcontext);
236 funcctx = SRF_PERCALL_SETUP();
237 tuple_desc = funcctx->tuple_desc;
240 if (funcctx->call_cntr < funcctx->max_calls) {
253 values = palloc(4 *
sizeof(Datum));
254 nulls = palloc(4 *
sizeof(
bool));
258 for (i = 0; i < 4; ++i) {
263 values[0] = Int32GetDatum(funcctx->call_cntr + 1);
264 values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr].
node);
265 values[2] = Float8GetDatum(result_tuples[funcctx->call_cntr].
cost);
266 values[3] = Float8GetDatum(result_tuples[funcctx->call_cntr].
agg_cost);
269 tuple = heap_form_tuple(tuple_desc, values, nulls);
270 result = HeapTupleGetDatum(tuple);
271 SRF_RETURN_NEXT(funcctx, result);
273 SRF_RETURN_DONE(funcctx);