37 #include <utils/array.h>
39 #include "catalog/pg_type.h"
40 #include "utils/lsyscache.h"
43 #define INT8ARRAYOID 1016
65 PGDLLEXPORT Datum
_vrp_vroom(PG_FUNCTION_ARGS);
99 char *shipments_tws_sql,
102 char *breaks_tws_sql,
105 int32_t exploration_level,
111 size_t *result_count) {
112 clock_t start_loading = clock();
115 (*result_tuples) = NULL;
119 size_t total_jobs = 0;
125 size_t total_shipments = 0;
130 if (total_jobs == 0 && total_shipments == 0) {
132 ereport(WARNING, (errmsg(
"Insufficient data found on Jobs SQL and Shipments SQL query."),
133 errhint(
"%s, %s", jobs_sql, shipments_sql)));
134 }
else if (fn == 1) {
135 ereport(WARNING, (errmsg(
"Insufficient data found on Jobs SQL query."),
136 errhint(
"%s", jobs_sql)));
137 }
else if (fn == 2) {
138 ereport(WARNING, (errmsg(
"Insufficient data found on Shipments SQL query."),
139 errhint(
"%s", shipments_sql)));
142 (*result_tuples) = NULL;
148 size_t total_jobs_tws = 0;
155 size_t total_shipments_tws = 0;
156 if (shipments_tws_sql) {
158 &total_shipments_tws, is_plain);
162 size_t total_vehicles = 0;
165 if (total_vehicles == 0) {
166 ereport(WARNING, (errmsg(
"Insufficient data found on Vehicles SQL query."),
167 errhint(
"%s", vehicles_sql)));
169 (*result_tuples) = NULL;
175 size_t total_breaks = 0;
181 size_t total_breaks_tws = 0;
182 if (breaks_tws_sql) {
188 size_t total_matrix_rows = 0;
191 if (total_matrix_rows == 0) {
192 ereport(WARNING, (errmsg(
"Insufficient data found on Matrix SQL query."),
193 errhint(
"%s", matrix_sql)));
195 (*result_tuples) = NULL;
200 clock_t start_t = clock();
201 char *log_msg = NULL;
202 char *notice_msg = NULL;
203 char *err_msg = NULL;
205 int32_t loading_time = (int)((clock() - start_loading) / CLOCKS_PER_SEC) * 1000;
209 jobs_tws, total_jobs_tws,
210 shipments, total_shipments,
211 shipments_tws, total_shipments_tws,
212 vehicles, total_vehicles,
213 breaks, total_breaks,
214 breaks_tws, total_breaks_tws,
215 matrix_rows, total_matrix_rows,
228 time_msg(
"processing vrp_vroom", start_t, clock());
230 if (err_msg && (*result_tuples)) {
231 pfree(*result_tuples);
232 (*result_tuples) = NULL;
238 if (log_msg) pfree(log_msg);
239 if (notice_msg) pfree(notice_msg);
240 if (err_msg) pfree(err_msg);
242 if (jobs) pfree(jobs);
243 if (shipments) pfree(shipments);
244 if (vehicles) pfree(vehicles);
245 if (matrix_rows) pfree(matrix_rows);
256 FuncCallContext *funcctx;
257 TupleDesc tuple_desc;
261 size_t result_count = 0;
264 if (SRF_IS_FIRSTCALL()) {
265 MemoryContext oldcontext;
266 funcctx = SRF_FIRSTCALL_INIT();
267 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
289 for (
int i = 0; i < 8; i++) {
290 if (PG_ARGISNULL(i)) {
293 args[i] = text_to_cstring(PG_GETARG_TEXT_P(i));
297 int32_t exploration_level = PG_GETARG_INT32(8);
298 int32_t timeout = PG_GETARG_INT32(9);
299 int16_t fn = PG_GETARG_INT16(10);
300 bool is_plain = PG_GETARG_BOOL(11);
303 if (args[0] == NULL && args[2] == NULL) {
305 elog(ERROR,
"Both Jobs SQL and Shipments NULL must not be NULL");
306 }
else if (fn == 1) {
307 elog(ERROR,
"Jobs SQL must not be NULL");
308 }
else if (fn == 2) {
309 elog(ERROR,
"Shipments SQL must not be NULL");
313 if (args[4] == NULL) {
314 elog(ERROR,
"Vehicles SQL must not be NULL");
317 if (args[7] == NULL) {
318 elog(ERROR,
"Matrix SQL must not be NULL");
340 #if PGSQL_VERSION > 95
341 funcctx->max_calls = result_count;
343 funcctx->max_calls = (uint32_t)result_count;
345 funcctx->user_fctx = result_tuples;
346 if (get_call_result_type(fcinfo, NULL, &tuple_desc)
347 != TYPEFUNC_COMPOSITE) {
349 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
350 errmsg(
"function returning record called in context "
351 "that cannot accept type record")));
354 funcctx->tuple_desc = tuple_desc;
355 MemoryContextSwitchTo(oldcontext);
358 funcctx = SRF_PERCALL_SETUP();
359 tuple_desc = funcctx->tuple_desc;
360 result_tuples = (
Vroom_rt*) funcctx->user_fctx;
362 if (funcctx->call_cntr < funcctx->max_calls) {
368 size_t call_cntr = funcctx->call_cntr;
371 values = palloc(num *
sizeof(Datum));
372 nulls = palloc(num *
sizeof(
bool));
375 for (i = 0; i < num; ++i) {
379 size_t load_size = (size_t)result_tuples[call_cntr].load_size;
380 Datum* load = (Datum*) palloc(
sizeof(Datum) * (size_t)load_size);
382 for (i = 0; i < load_size; ++i) {
383 load[i] = Int64GetDatum(result_tuples[call_cntr].load[i]);
388 get_typlenbyvalalign(INT8OID, &typlen, &typbyval, &typalign);
389 ArrayType* arrayType;
398 arrayType = construct_array(load, (
int)load_size, INT8OID, typlen,
410 TupleDescInitEntry(tuple_desc, (AttrNumber) 16,
"load",
INT8ARRAYOID, -1, 0);
412 values[0] = Int64GetDatum(funcctx->call_cntr + 1);
413 values[1] = Int64GetDatum(result_tuples[call_cntr].vehicle_seq);
414 values[2] = Int64GetDatum(result_tuples[call_cntr].vehicle_id);
415 values[3] = CStringGetTextDatum(result_tuples[call_cntr].vehicle_data);
416 values[4] = Int64GetDatum(result_tuples[call_cntr].step_seq);
417 values[5] = Int32GetDatum(result_tuples[call_cntr].step_type);
418 values[6] = Int64GetDatum(result_tuples[call_cntr].task_id);
419 values[7] = Int64GetDatum(result_tuples[call_cntr].location_id);
420 values[8] = CStringGetTextDatum(result_tuples[call_cntr].task_data);
421 values[9] = Int32GetDatum(result_tuples[call_cntr].arrival_time);
422 values[10] = Int32GetDatum(result_tuples[call_cntr].travel_time);
423 values[11] = Int32GetDatum(result_tuples[call_cntr].setup_time);
424 values[12] = Int32GetDatum(result_tuples[call_cntr].service_time);
425 values[13] = Int32GetDatum(result_tuples[call_cntr].waiting_time);
426 values[14] = Int32GetDatum(result_tuples[call_cntr].departure_time);
427 values[15] = PointerGetDatum(arrayType);
431 tuple = heap_form_tuple(tuple_desc, values, nulls);
432 result = HeapTupleGetDatum(tuple);
433 SRF_RETURN_NEXT(funcctx, result);
435 SRF_RETURN_DONE(funcctx);