diff --git a/configuration.conf b/configuration.conf index a62969adf8d..f21b3c6f465 100644 --- a/configuration.conf +++ b/configuration.conf @@ -14,6 +14,7 @@ common | Y | Y | Y # Has the command needed to link with prostgresl #---------------------- dijkstra | Y | Y | Y +funnyDijkstra | Y | Y | Y allpairs | Y | Y | Y astar | Y | Y | Y driving_distance | Y | Y | Y diff --git a/doc/funnyDijkstra/CMakeLists.txt b/doc/funnyDijkstra/CMakeLists.txt new file mode 100644 index 00000000000..5493f0b9dbe --- /dev/null +++ b/doc/funnyDijkstra/CMakeLists.txt @@ -0,0 +1,13 @@ + +SET(LOCAL_FILES + pgr_funnyDijkstra.rst + doc-pgr_funnyDijkstra.queries + ) + +foreach (f ${LOCAL_FILES}) + configure_file(${f} "${PGR_DOCUMENTATION_SOURCE_DIR}/${f}") + list(APPEND LOCAL_DOC_FILES ${PGR_DOCUMENTATION_SOURCE_DIR}/${f}) +endforeach() + +set(PgRouting_DOC_FILES ${PgRouting_DOC_FILES} ${LOCAL_DOC_FILES} PARENT_SCOPE) + diff --git a/doc/funnyDijkstra/doc-pgr_funnyDijkstra.queries b/doc/funnyDijkstra/doc-pgr_funnyDijkstra.queries new file mode 100644 index 00000000000..15a1994108c --- /dev/null +++ b/doc/funnyDijkstra/doc-pgr_funnyDijkstra.queries @@ -0,0 +1,32 @@ +BEGIN; +BEGIN +-- q1 +SELECT * FROM pgr_funnyDijkstra( + 'SELECT id, source, target, cost, reverse_cost FROM edge_table', + 2, 3 +); + seq | path_seq | node | edge | cost | agg_cost +-----+----------+------+------+------+---------- + 1 | 1 | 2 | 4 | 1 | 0 + 2 | 2 | 5 | 8 | 1 | 1 + 3 | 3 | 6 | 9 | 1 | 2 + 4 | 4 | 9 | 16 | 1 | 3 + 5 | 5 | 4 | 3 | 1 | 4 + 6 | 6 | 3 | -1 | 0 | 5 +(6 rows) + +-- q2 +SELECT * FROM pgr_funnyDijkstra( + 'SELECT id, source, target, cost, reverse_cost FROM edge_table', + 2, 3, + FALSE +); + seq | path_seq | node | edge | cost | agg_cost +-----+----------+------+------+------+---------- + 1 | 1 | 2 | 2 | 1 | 0 + 2 | 2 | 3 | -1 | 0 | 1 +(2 rows) + +-- q3 +ROLLBACK; +ROLLBACK diff --git a/doc/funnyDijkstra/pgr_funnyDijkstra.rst b/doc/funnyDijkstra/pgr_funnyDijkstra.rst new file mode 100644 index 00000000000..45e2f62bbb8 --- /dev/null +++ b/doc/funnyDijkstra/pgr_funnyDijkstra.rst @@ -0,0 +1,141 @@ +.. + **************************************************************************** + pgRouting Manual + Copyright(c) pgRouting Contributors + + This documentation is licensed under a Creative Commons Attribution-Share + Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/ + **************************************************************************** + +.. _pgr_funnyDijkstra: + +pgr_funnyDijkstra +=============================================================================== + +``pgr_funnyDijkstra`` — Returns the shortest path(s) using Dijkstra algorithm. +In particular, the Dijkstra algorithm implemented by Boost.Graph. + +.. figure:: images/boost-inside.jpeg + :target: http://www.boost.org/libs/graph/doc/dijkstra_shortest_paths.html + + Boost Graph Inside + + +Synopsis +------------------------------------------------------------------------------- + +Dijkstra's algorithm, conceived by Dutch computer scientist Edsger Dijkstra in 1956. +It is a graph search algorithm that solves the shortest path problem for +a graph with non-negative edge path costs, producing a shortest path from +a starting vertex (``start_vid``) to an ending vertex (``end_vid``). +This implementation can be used with a directed graph and an undirected graph. + +Characteristics +------------------------------------------------------------------------------- + +The main Characteristics are: + - Process is done only on edges with positive costs. + - Values are returned when there is a path. + + - When the starting vertex and ending vertex are the same, there is no path. + + - The `agg_cost` the non included values `(v, v)` is `0` + + - When the starting vertex and ending vertex are the different and there is no path: + + - The `agg_cost` the non included values `(u, v)` is :math:`\infty` + + - For optimization purposes, any duplicated value in the `start_vids` or `end_vids` are ignored. + + - The returned values are ordered: + + - `start_vid` ascending + - `end_vid` ascending + + - Running time: :math:`O(| start\_vids | * (V \log V + E))` + + +Signature Summary +----------------- + +.. code-block:: none + + pgr_dijkstra(edges_sql, start_vid, end_vid) + + RETURNS SET OF (seq, path_seq, node, edge, cost, agg_cost) + OR EMPTY SET + + +Signatures +------------------------------------------------------------------------------- + +.. index:: + single: funnyDijkstra(Minimal Use) + +Minimal signature +....................................... + +.. code-block:: none + + pgr_funnyDijkstra(edges_sql, start_vid, end_vid) + RETURNS SET OF (seq, path_seq, node, edge, cost, agg_cost) or EMPTY SET + +The minimal signature is for a **directed** graph from one ``start_vid`` to one ``end_vid``: + +:Example: + +.. literalinclude:: doc-pgr_funnyDijkstra.queries + :start-after: -- q1 + :end-before: -- q2 + + +.. index:: + single: funnyDijkstra(Complete signature) + +Complete Signature +....................................... + +.. code-block:: none + + pgr_funnyDijkstra(edges_sql, start_vid, end_vid, directed); + RETURNS SET OF (seq, path_seq, node, edge, cost, agg_cost) or EMPTY SET + +This signature finds the shortest path from one ``start_vid`` to one ``end_vid``: + - on a **directed** graph when ``directed`` flag is missing or is set to ``true``. + - on an **undirected** graph when ``directed`` flag is set to ``false``. + +:Example: + +.. literalinclude:: doc-pgr_funnyDijkstra.queries + :start-after: -- q2 + :end-before: -- q3 + + + +Description of the Signatures +------------------------------------------------------------------------------- + +.. include:: pgRouting-concepts.rst + :start-after: basic_edges_sql_start + :end-before: basic_edges_sql_end + +.. include:: pgr_dijkstra.rst + :start-after: pgr_dijkstra_parameters_start + :end-before: pgr_dijkstra_parameters_end + +.. include:: pgRouting-concepts.rst + :start-after: return_path_start + :end-before: return_path_end + + +See Also +------------------------------------------------------------------------------- + +* http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm +* The queries use the :ref:`sampledata` network. + +.. rubric:: Indices and tables + +* :ref:`genindex` +* :ref:`search` + diff --git a/include/drivers/funnyDijkstra/funnyDijkstra_driver.h b/include/drivers/funnyDijkstra/funnyDijkstra_driver.h new file mode 100644 index 00000000000..d571449a030 --- /dev/null +++ b/include/drivers/funnyDijkstra/funnyDijkstra_driver.h @@ -0,0 +1,69 @@ +/*PGR-GNU***************************************************************** +File: funnyDijkstra_driver.h + +Generated with Template by: +Copyright (c) 2015 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2015 Celia Virginia Vergara Castillo +Mail: vicky_vergara@hotmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +********************************************************************PGR-GNU*/ + +#ifndef INCLUDE_DRIVERS_FUNNYDIJKSTRA_FUNNYDIJKSTRA_DRIVER_H_ +#define INCLUDE_DRIVERS_FUNNYDIJKSTRA_FUNNYDIJKSTRA_DRIVER_H_ +#pragma once + +#include "c_types/pgr_edge_t.h" +#include "c_types/general_path_element_t.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /********************************************************* + TEXT, + BIGINT, + BIGINT, + directed BOOLEAN DEFAULT true, + only_cost BOOLEAN DEFAULT false, + ********************************************************/ + + + void + do_pgr_funnyDijkstra( + pgr_edge_t *data_edges, + size_t total_edges, + int64_t start_vid, + int64_t end_vid, + bool directed, + bool only_cost, + General_path_element_t **return_tuples, + size_t *return_count, + char ** log_msg, + char ** notice_msg, + char ** err_msg); + + +#ifdef __cplusplus +} +#endif + +#endif // INCLUDE_DRIVERS_FUNNYDIJKSTRA_FUNNYDIJKSTRA_DRIVER_H_ diff --git a/pgtap/funnyDijkstra/funnyDijkstra-compare-dijkstra.sql b/pgtap/funnyDijkstra/funnyDijkstra-compare-dijkstra.sql new file mode 100644 index 00000000000..88ebc8b3e02 --- /dev/null +++ b/pgtap/funnyDijkstra/funnyDijkstra-compare-dijkstra.sql @@ -0,0 +1,73 @@ +\i setup.sql + +SELECT plan(1156); + +SET client_min_messages TO ERROR; + +UPDATE edge_table SET cost = cost + 0.001 * id * id, reverse_cost = reverse_cost + 0.001 * id * id; + +CREATE or REPLACE FUNCTION funnydijkstra_compare_dijkstra(cant INTEGER default 17) +RETURNS SETOF TEXT AS +$BODY$ +DECLARE +inner_sql TEXT; +dijkstra_sql TEXT; +funnydijkstra_sql TEXT; +BEGIN + + FOR i IN 1.. cant LOOP + FOR j IN 1.. cant LOOP + + -- DIRECTED + inner_sql := 'SELECT id, source, target, cost, reverse_cost FROM edge_table'; + dijkstra_sql := 'SELECT * FROM pgr_dijkstra($$' || inner_sql || '$$, ' || i || ', ' || j + || ', true)'; + + funnydijkstra_sql := 'SELECT * FROM pgr_funnydijkstra($$' || inner_sql || '$$, ' || i || ', ' || j + || ', true)'; + RETURN query SELECT set_eq(funnydijkstra_sql, dijkstra_sql, funnydijkstra_sql); + + + inner_sql := 'SELECT id, source, target, cost FROM edge_table'; + dijkstra_sql := 'SELECT * FROM pgr_dijkstra($$' || inner_sql || '$$, ' || i || ', ' || j + || ', true)'; + + funnydijkstra_sql := 'SELECT * FROM pgr_funnydijkstra($$' || inner_sql || '$$, ' || i || ', ' || j + || ', true)'; + RETURN query SELECT set_eq(funnydijkstra_sql, dijkstra_sql, funnydijkstra_sql); + + + + -- UNDIRECTED + inner_sql := 'SELECT id, source, target, cost, reverse_cost FROM edge_table'; + dijkstra_sql := 'SELECT * FROM pgr_dijkstra($$' || inner_sql || '$$, ' || i || ', ' || j + || ', false)'; + + funnydijkstra_sql := 'SELECT * FROM pgr_funnydijkstra($$' || inner_sql || '$$, ' || i || ', ' || j + || ', false)'; + RETURN query SELECT set_eq(funnydijkstra_sql, dijkstra_sql, funnydijkstra_sql); + + + inner_sql := 'SELECT id, source, target, cost FROM edge_table'; + dijkstra_sql := 'SELECT * FROM pgr_dijkstra($$' || inner_sql || '$$, ' || i || ', ' || j + || ', false)'; + + funnydijkstra_sql := 'SELECT * FROM pgr_funnydijkstra($$' || inner_sql || '$$, ' || i || ', ' || j + || ', false)'; + RETURN query SELECT set_eq(funnydijkstra_sql, dijkstra_sql, funnydijkstra_sql); + + + END LOOP; + END LOOP; + + RETURN; +END +$BODY$ +language plpgsql; + +SELECT * from funnydijkstra_compare_dijkstra(); + + +SELECT * FROM finish(); +ROLLBACK; + diff --git a/pgtap/funnyDijkstra/funnyDijkstra-innerQuery.sql b/pgtap/funnyDijkstra/funnyDijkstra-innerQuery.sql new file mode 100644 index 00000000000..ad1584d7c1c --- /dev/null +++ b/pgtap/funnyDijkstra/funnyDijkstra-innerQuery.sql @@ -0,0 +1,21 @@ +\i setup.sql + +SELECT plan(137); +SET client_min_messages TO ERROR; + + +SELECT has_function('pgr_funnydijkstra', + ARRAY['text', 'bigint', 'bigint', 'boolean','boolean']); + +SELECT function_returns('pgr_funnydijkstra', + ARRAY['text', 'bigint', 'bigint', 'boolean','boolean'], + 'setof record'); + +SELECT style_dijkstra('pgr_funnydijkstra', ', 2, 3)'); +SELECT style_dijkstra('pgr_funnydijkstra', ', 2, 3, true)'); +SELECT style_dijkstra('pgr_funnydijkstra', ', 2, 3, false)'); + + + +SELECT finish(); +ROLLBACK; diff --git a/pgtap/funnyDijkstra/funnyDijkstra-typesCheck.sql b/pgtap/funnyDijkstra/funnyDijkstra-typesCheck.sql new file mode 100644 index 00000000000..267e71c4971 --- /dev/null +++ b/pgtap/funnyDijkstra/funnyDijkstra-typesCheck.sql @@ -0,0 +1,15 @@ + +SELECT plan(4); + +SELECT has_function('pgr_funnydijkstra'); + +SELECT has_function('pgr_funnydijkstra', ARRAY[ 'text', 'bigint', 'bigint', 'boolean', 'boolean' ]); + +SELECT function_returns('pgr_funnydijkstra', ARRAY[ 'text', 'bigint', 'bigint', 'boolean', 'boolean' ], 'setof record'); + +-- testing column names +SELECT bag_has( + $$SELECT proargnames from pg_proc where proname = 'pgr_funnydijkstra'$$, + $$SELECT '{"","","","directed","only_cost","seq","path_seq","node","edge","cost","agg_cost"}'::TEXT[] $$ +); + diff --git a/sql/funnyDijkstra/CMakeLists.txt b/sql/funnyDijkstra/CMakeLists.txt new file mode 100644 index 00000000000..e91c3a4f770 --- /dev/null +++ b/sql/funnyDijkstra/CMakeLists.txt @@ -0,0 +1,13 @@ + +SET(LOCAL_FILES + funnyDijkstra.sql + ) + +# Do not modify bellow this line + +foreach (f ${LOCAL_FILES}) + configure_file(${f} ${f}) + list(APPEND PACKAGE_SQL_FILES ${CMAKE_CURRENT_BINARY_DIR}/${f}) +endforeach() + +set(PgRouting_SQL_FILES ${PgRouting_SQL_FILES} ${PACKAGE_SQL_FILES} PARENT_SCOPE) diff --git a/sql/funnyDijkstra/funnyDijkstra.sql b/sql/funnyDijkstra/funnyDijkstra.sql new file mode 100644 index 00000000000..978f3b3e0c2 --- /dev/null +++ b/sql/funnyDijkstra/funnyDijkstra.sql @@ -0,0 +1,46 @@ +/*PGR-GNU***************************************************************** +File: funnyDijkstra.sql + +Generated with Template by: +Copyright (c) 2016 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2017 Celia Virginia Vergara Castillo +Mail: vicky_vergara@hotmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +********************************************************************PGR-GNU*/ + +CREATE OR REPLACE FUNCTION pgr_funnyDijkstra( + TEXT, + BIGINT, + BIGINT, + directed BOOLEAN DEFAULT true, + only_cost BOOLEAN DEFAULT false, + OUT seq INTEGER, + OUT path_seq INTEGER, + OUT node BIGINT, + OUT edge BIGINT, + OUT cost FLOAT, + OUT agg_cost FLOAT) + +RETURNS SETOF RECORD AS +'$libdir/${PGROUTING_LIBRARY_NAME}', 'funnyDijkstra' +LANGUAGE c IMMUTABLE STRICT; + diff --git a/src/funnyDijkstra/CMakeLists.txt b/src/funnyDijkstra/CMakeLists.txt new file mode 100644 index 00000000000..3dfc5ee040d --- /dev/null +++ b/src/funnyDijkstra/CMakeLists.txt @@ -0,0 +1,4 @@ +ADD_LIBRARY(funnyDijkstra OBJECT + funnyDijkstra.c + funnyDijkstra_driver.cpp + ) diff --git a/src/funnyDijkstra/funnyDijkstra.c b/src/funnyDijkstra/funnyDijkstra.c new file mode 100644 index 00000000000..a889b69f0c8 --- /dev/null +++ b/src/funnyDijkstra/funnyDijkstra.c @@ -0,0 +1,306 @@ +/*PGR-GNU***************************************************************** +File: funnyDijkstra.c + +Generated with Template by: +Copyright (c) 2015 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2017 Celia Virginia Vergara Castillo +Mail: vicky_vergara@hotmail.com + + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +********************************************************************PGR-GNU*/ + +/** @file funnyDijkstra.c + * @brief Conecting code with postgres. + * + * This file is fully documented for understanding + * how the postgres connectinon works + * + * TODO Remove unnecessary comments before submiting the function. + * some comments are in form of PGR_DBG message + */ + +/** + * postgres_connection.h + * + * - should allways be first in the C code + */ +#include "c_common/postgres_connection.h" + + +/* for macro PGR_DBG */ +#include "c_common/debug_macro.h" +/* for pgr_global_report */ +#include "c_common/e_report.h" +/* for time_msg & clock */ +#include "c_common/time_msg.h" +/* for functions to get edges informtion */ +#include "c_common/edges_input.h" + +#include "drivers/funnyDijkstra/funnyDijkstra_driver.h" // the link to the C++ code of the function + +PGDLLEXPORT Datum funnyDijkstra(PG_FUNCTION_ARGS); +PG_FUNCTION_INFO_V1(funnyDijkstra); + + +/******************************************************************************/ +/* 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, + General_path_element_t **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"); + pgr_edge_t *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; + } + + 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_funnyDijkstra( + 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_funnyDijkstra", 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(); +} +/* */ +/******************************************************************************/ + +PGDLLEXPORT Datum funnyDijkstra(PG_FUNCTION_ARGS) { + FuncCallContext *funcctx; + TupleDesc tuple_desc; + + /**************************************************************************/ + /* MODIFY AS NEEDED */ + /* */ + General_path_element_t *result_tuples = NULL; + 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 */ + /* + TEXT, + BIGINT, + BIGINT, + directed BOOLEAN DEFAULT true, + only_cost BOOLEAN DEFAULT false, + **********************************************************************/ + + + PGR_DBG("Calling process"); + process( + text_to_cstring(PG_GETARG_TEXT_P(0)), + PG_GETARG_INT64(1), + PG_GETARG_INT64(2), +#if 0 + /* + * handling arrays example + */ + + PG_GETARG_ARRAYTYPE_P(1), + PG_GETARG_ARRAYTYPE_P(2), +#endif + PG_GETARG_BOOL(3), + PG_GETARG_BOOL(4), + &result_tuples, + &result_count); + + + /* */ + /**********************************************************************/ + +#if PGSQL_VERSION > 94 + funcctx->max_calls = result_count; +#else + funcctx->max_calls = (uint32_t)result_count; +#endif + 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(); + tuple_desc = funcctx->tuple_desc; + result_tuples = (General_path_element_t*) funcctx->user_fctx; + + if (funcctx->call_cntr < funcctx->max_calls) { + HeapTuple tuple; + Datum result; + Datum *values; + bool* nulls; + + /**********************************************************************/ + /* MODIFY AS NEEDED */ + /* + OUT seq INTEGER, + OUT path_seq INTEGER, + OUT node BIGINT, + OUT edge BIGINT, + OUT cost FLOAT, + OUT agg_cost FLOAT + ***********************************************************************/ + + values = palloc(6 * sizeof(Datum)); + nulls = palloc(6 * sizeof(bool)); + + + size_t i; + for (i = 0; i < 6; ++i) { + nulls[i] = false; + } + + // postgres starts counting from 1 + values[0] = Int32GetDatum(funcctx->call_cntr + 1); + values[1] = Int32GetDatum(result_tuples[funcctx->call_cntr].seq); + values[2] = Int64GetDatum(result_tuples[funcctx->call_cntr].node); + values[3] = Int64GetDatum(result_tuples[funcctx->call_cntr].edge); + values[4] = Float8GetDatum(result_tuples[funcctx->call_cntr].cost); + values[5] = Float8GetDatum(result_tuples[funcctx->call_cntr].agg_cost); + /**********************************************************************/ + + tuple = heap_form_tuple(tuple_desc, values, nulls); + result = HeapTupleGetDatum(tuple); + SRF_RETURN_NEXT(funcctx, result); + } else { + /**********************************************************************/ + /* MODIFY AS NEEDED */ + + PGR_DBG("Clean up code"); + + /**********************************************************************/ + + SRF_RETURN_DONE(funcctx); + } +} diff --git a/src/funnyDijkstra/funnyDijkstra_driver.cpp b/src/funnyDijkstra/funnyDijkstra_driver.cpp new file mode 100644 index 00000000000..5502657e2dd --- /dev/null +++ b/src/funnyDijkstra/funnyDijkstra_driver.cpp @@ -0,0 +1,155 @@ +/*PGR-GNU***************************************************************** +File: funnyDijkstra_driver.cpp + +Generated with Template by: +Copyright (c) 2015 pgRouting developers +Mail: project@pgrouting.org + +Function's developer: +Copyright (c) 2017 Celia Virginia Vergara Castillo +Mail: vicky_vergara@hotmail.com + +------ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +********************************************************************PGR-GNU*/ + +#include "drivers/funnyDijkstra/funnyDijkstra_driver.h" + +#include +#include +#include + +#include "dijkstra/pgr_dijkstra.hpp" + +#include "cpp_common/pgr_alloc.hpp" +#include "cpp_common/pgr_assert.h" + + + + + +/************************************************************ + TEXT, + BIGINT, + BIGINT, + directed BOOLEAN DEFAULT true, + only_cost BOOLEAN DEFAULT false, + ***********************************************************/ + +template < class G > +static +Path +pgr_funnyDijkstra( + G &graph, + int64_t source, + int64_t target, + bool only_cost = false) { + Path path; + Pgr_dijkstra< G > fn_dijkstra; + return fn_dijkstra.dijkstra(graph, source, target, only_cost); +} + + +void +do_pgr_funnyDijkstra( + pgr_edge_t *data_edges, + size_t total_edges, + int64_t start_vid, + int64_t end_vid, + bool directed, + bool only_cost, + General_path_element_t **return_tuples, + size_t *return_count, + char ** log_msg, + char ** notice_msg, + char ** err_msg) { + std::ostringstream log; + std::ostringstream err; + std::ostringstream notice; + try { + pgassert(!(*log_msg)); + pgassert(!(*notice_msg)); + pgassert(!(*err_msg)); + pgassert(!(*return_tuples)); + pgassert(*return_count == 0); + pgassert(total_edges != 0); + + graphType gType = directed? DIRECTED: UNDIRECTED; + + Path path; + + if (directed) { + log << "Working with directed Graph\n"; + pgrouting::DirectedGraph digraph(gType); + digraph.insert_edges(data_edges, total_edges); + path = pgr_funnyDijkstra(digraph, + start_vid, + end_vid, + only_cost); + } else { + log << "Working with Undirected Graph\n"; + pgrouting::UndirectedGraph undigraph(gType); + undigraph.insert_edges(data_edges, total_edges); + path = pgr_funnyDijkstra( + undigraph, + start_vid, + end_vid, + only_cost); + } + + auto count = path.size(); + + if (count == 0) { + (*return_tuples) = NULL; + (*return_count) = 0; + notice << + "No paths found between start_vid and end_vid vertices"; + return; + } + + (*return_tuples) = pgr_alloc(count, (*return_tuples)); + size_t sequence = 0; + path.generate_postgres_data(return_tuples, sequence); + (*return_count) = sequence; + + pgassert(*err_msg == NULL); + *log_msg = log.str().empty()? + *log_msg : + pgr_msg(log.str().c_str()); + *notice_msg = notice.str().empty()? + *notice_msg : + pgr_msg(notice.str().c_str()); + } catch (AssertFailedException &except) { + (*return_tuples) = pgr_free(*return_tuples); + (*return_count) = 0; + err << except.what(); + *err_msg = pgr_msg(err.str().c_str()); + *log_msg = pgr_msg(log.str().c_str()); + } catch (std::exception &except) { + (*return_tuples) = pgr_free(*return_tuples); + (*return_count) = 0; + err << except.what(); + *err_msg = pgr_msg(err.str().c_str()); + *log_msg = pgr_msg(log.str().c_str()); + } catch(...) { + (*return_tuples) = pgr_free(*return_tuples); + (*return_count) = 0; + err << "Caught unknown exception!"; + *err_msg = pgr_msg(err.str().c_str()); + *log_msg = pgr_msg(log.str().c_str()); + } +} diff --git a/test/funnyDijkstra/doc-funnyDijkstra.result b/test/funnyDijkstra/doc-funnyDijkstra.result new file mode 100644 index 00000000000..b5ef186b013 --- /dev/null +++ b/test/funnyDijkstra/doc-funnyDijkstra.result @@ -0,0 +1,34 @@ +BEGIN; +BEGIN +SET client_min_messages TO NOTICE; +SET +-- q1 +SELECT * FROM pgr_funnyDijkstra( + 'SELECT id, source, target, cost, reverse_cost FROM edge_table', + 2, 3 +); + seq | path_seq | node | edge | cost | agg_cost +-----+----------+------+------+------+---------- + 1 | 1 | 2 | 4 | 1 | 0 + 2 | 2 | 5 | 8 | 1 | 1 + 3 | 3 | 6 | 9 | 1 | 2 + 4 | 4 | 9 | 16 | 1 | 3 + 5 | 5 | 4 | 3 | 1 | 4 + 6 | 6 | 3 | -1 | 0 | 5 +(6 rows) + +-- q2 +SELECT * FROM pgr_funnyDijkstra( + 'SELECT id, source, target, cost, reverse_cost FROM edge_table', + 2, 3, + FALSE +); + seq | path_seq | node | edge | cost | agg_cost +-----+----------+------+------+------+---------- + 1 | 1 | 2 | 2 | 1 | 0 + 2 | 2 | 3 | -1 | 0 | 1 +(2 rows) + +-- q3 +ROLLBACK; +ROLLBACK diff --git a/test/funnyDijkstra/doc-funnyDijkstra.test.sql b/test/funnyDijkstra/doc-funnyDijkstra.test.sql new file mode 100644 index 00000000000..0b3e28f4f34 --- /dev/null +++ b/test/funnyDijkstra/doc-funnyDijkstra.test.sql @@ -0,0 +1,15 @@ + +\echo -- q1 +SELECT * FROM pgr_funnyDijkstra( + 'SELECT id, source, target, cost, reverse_cost FROM edge_table', + 2, 3 +); + +\echo -- q2 +SELECT * FROM pgr_funnyDijkstra( + 'SELECT id, source, target, cost, reverse_cost FROM edge_table', + 2, 3, + FALSE +); +\echo -- q3 + diff --git a/test/funnyDijkstra/myTest.result b/test/funnyDijkstra/myTest.result new file mode 100644 index 00000000000..6a2d8fc3cde --- /dev/null +++ b/test/funnyDijkstra/myTest.result @@ -0,0 +1,18 @@ +BEGIN; +BEGIN +SET client_min_messages TO NOTICE; +SET +-- q1 +SELECT * FROM pgr_funnyDijkstra( + 'SELECT id, source, target, cost, reverse_cost FROM edge_table', + 4, 3 +); + seq | path_seq | node | edge | cost | agg_cost +-----+----------+------+------+------+---------- + 1 | 1 | 4 | 3 | 1 | 0 + 2 | 2 | 3 | -1 | 0 | 1 +(2 rows) + +-- q2 +ROLLBACK; +ROLLBACK diff --git a/test/funnyDijkstra/myTest.test.sql b/test/funnyDijkstra/myTest.test.sql new file mode 100644 index 00000000000..75283d05918 --- /dev/null +++ b/test/funnyDijkstra/myTest.test.sql @@ -0,0 +1,7 @@ +\echo -- q1 +SELECT * FROM pgr_funnyDijkstra( + 'SELECT id, source, target, cost, reverse_cost FROM edge_table', + 4, 3 +); + +\echo -- q2 diff --git a/test/funnyDijkstra/test.conf b/test/funnyDijkstra/test.conf new file mode 100644 index 00000000000..b421bd49e7f --- /dev/null +++ b/test/funnyDijkstra/test.conf @@ -0,0 +1,17 @@ +#!/usr/bin/perl -w + +%main::tests = ( + 'any' => { + 'comment' => 'Dijkstra test for any versions.', + 'data' => [ ], + 'tests' => [qw( + myTest + )], + 'documentation' => [qw( + doc-funnyDijkstra + )] + }, + +); + +1;