Пример #1
0
/*
 * This function fetches the edge columns from the SPITupleTable.
 * 
*/ 
static int
fetch_edge_columns(SPITupleTable *tuptable, edge_columns_t *edge_columns, 
                   bool has_reverse_cost)
{
  edge_columns->id = SPI_fnumber(SPI_tuptable->tupdesc, "id");
  edge_columns->source = SPI_fnumber(SPI_tuptable->tupdesc, "source");
  edge_columns->target = SPI_fnumber(SPI_tuptable->tupdesc, "target");
  edge_columns->cost = SPI_fnumber(SPI_tuptable->tupdesc, "cost");
  if (edge_columns->id == SPI_ERROR_NOATTRIBUTE ||
      edge_columns->source == SPI_ERROR_NOATTRIBUTE ||
      edge_columns->target == SPI_ERROR_NOATTRIBUTE ||
      edge_columns->cost == SPI_ERROR_NOATTRIBUTE) 
    {
      elog(ERROR, "Error, query must return columns "
           "'id', 'source', 'target' and 'cost'");
      return -1;
    }

  if (SPI_gettypeid(SPI_tuptable->tupdesc, edge_columns->source) != INT4OID ||
      SPI_gettypeid(SPI_tuptable->tupdesc, edge_columns->target) != INT4OID ||
      SPI_gettypeid(SPI_tuptable->tupdesc, edge_columns->cost) != FLOAT8OID) 
    {
      elog(ERROR, "Error, columns 'source', 'target' must be of type int4, 'cost' must be of type float8");
      return -1;
    }

  PGR_DBG("columns: id %i source %i target %i cost %i", 
      edge_columns->id, edge_columns->source, 
      edge_columns->target, edge_columns->cost);

  if (has_reverse_cost)
    {
      edge_columns->reverse_cost = SPI_fnumber(SPI_tuptable->tupdesc, 
                                               "reverse_cost");

      if (edge_columns->reverse_cost == SPI_ERROR_NOATTRIBUTE) 
        {
          elog(ERROR, "Error, reverse_cost is used, but query did't return "
               "'reverse_cost' column");
          return -1;
        }

      if (SPI_gettypeid(SPI_tuptable->tupdesc, edge_columns->reverse_cost) 
          != FLOAT8OID) 
        {
          elog(ERROR, "Error, columns 'reverse_cost' must be of type float8");
          return -1;
        }

      PGR_DBG("columns: reverse_cost cost %i", edge_columns->reverse_cost);
    }
    
  return 0;
}
Пример #2
0
double
pgr_SPI_getFloat8(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info) {
    Datum binval;
    bool isnull;
    double value = 0.0;
    binval = SPI_getbinval(*tuple, *tupdesc, info.colNumber, &isnull);
    if (isnull)
        elog(ERROR, "Unexpected Null value in column %s", info.name);

    switch (info.type) {
        case INT2OID:
            value = (double) DatumGetInt16(binval);
            break;
        case INT4OID:
            value = (double) DatumGetInt32(binval);
            break;
        case INT8OID:
            value = (double) DatumGetInt64(binval);
            break;
        case FLOAT4OID:
            value = (double) DatumGetFloat4(binval);
            break;
        case FLOAT8OID:
            value = DatumGetFloat8(binval);
            break;
        default:
            elog(ERROR,
                    "Unexpected Column type of %s. Expected ANY-NUMERICAL",
                    info.name);
    }
    PGR_DBG("Variable: %s Value: %lf", info.name, value);
    return value;
}
Пример #3
0
int64_t
pgr_SPI_getBigInt(HeapTuple *tuple, TupleDesc *tupdesc, Column_info_t info) {
    Datum binval;
    bool isnull;
    int64_t value = 0;
    binval = SPI_getbinval(*tuple, *tupdesc, info.colNumber, &isnull);
    if (isnull)
        elog(ERROR, "Unexpected Null value in column %s", info.name);
    switch (info.type) {
        case INT2OID:
            value = (int64_t) DatumGetInt16(binval);
            break;
        case INT4OID:
            value = (int64_t) DatumGetInt32(binval);
            break;
        case INT8OID:
            value = DatumGetInt64(binval);
            break;
        default:
            elog(ERROR,
                    "Unexpected Column type of %s. Expected ANY-INTEGER",
                    info.name);
    }
    PGR_DBG("Variable: %s Value: %lld", info.name, value);
    return value;
}
// http://www.postgresql.org/docs/9.4/static/spi-spi-finish.html
void
pgr_SPI_finish(void) {
    PGR_DBG("Disconnecting SPI");
    int code = SPI_OK_FINISH;
    code = SPI_finish();
    if (code != SPI_OK_FINISH) {  // SPI_ERROR_UNCONNECTED
        elog(ERROR, "There was no connection to SPI");
    }
}
void
pgr_SPI_connect(void) {
    PGR_DBG("Connecting to SPI");
    int SPIcode;
    SPIcode = SPI_connect();
    if (SPIcode  != SPI_OK_CONNECT) {
        elog(ERROR, "Couldn't open a connection to SPI");
    }
}
Пример #6
0
static
void
process(char* edges_sql,
        bool *result_bool) {
    pgr_SPI_connect();

    PGR_DBG("Load data");
    Pgr_edge_xy_t *edges = NULL;
    size_t total_edges = 0;
    pgr_get_edges_xy(edges_sql, &edges, &total_edges);

    if (total_edges == 0) {
        PGR_DBG("No edges found");
        (*result_bool) = true;
        pfree(edges);
        pgr_SPI_finish();
        return;
    }
    PGR_DBG("Total %ld tuples in query:", total_edges);
    size_t i;
    for (i = 0; i < total_edges; ++i) {
        PGR_DBG("id = %li \t source = %li \t target = %ld  cost = %lf reverse_cost = %lf",
               edges[i].id, edges[i].source, edges[i].target, edges[i].cost, edges[i].reverse_cost);
        PGR_DBG("    (x1,y1) = (%.32lf ,%.32lf) (x2,y2) = (%.32lf,.%.32lf)",
               edges[i].x1, edges[i].y1, edges[i].x2, edges[i].y2);
    }


    PGR_DBG("Starting processing");
    char *err_msg = NULL;
    char *log_msg = NULL;
    (*result_bool) = do_pgr_testXYedges(
            edges,
            total_edges,
            &log_msg,
            &err_msg);

    pfree(edges);
    PGR_DBG("Returned log message = %s\n", log_msg);
    if (log_msg) {
        elog(DEBUG1, "%s", log_msg);
        free(log_msg);
    }
    PGR_DBG("Returned error message = %s\n", err_msg);

    if (err_msg) {
        pgr_SPI_finish();
        elog(ERROR, "%s", err_msg);
        free(err_msg);
    }

    pgr_SPI_finish();
}
Portal
pgr_SPI_cursor_open(SPIPlanPtr SPIplan) {
    PGR_DBG("Opening Portal");
    Portal SPIportal;
    SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true);
    if (SPIportal == NULL) {
        elog(ERROR, "SPI_cursor_open returns NULL");
    }
    return SPIportal;
}
SPIPlanPtr
pgr_SPI_prepare(char* sql) {
    PGR_DBG("Preparing Plan");
    SPIPlanPtr SPIplan;
    SPIplan = SPI_prepare(sql, 0, NULL);
    if (SPIplan  == NULL) {
        elog(ERROR, "Couldn't create query plan via SPI: %s", sql);
    }
    return SPIplan;
}
Пример #9
0
static
void annealing(TSP *tsp) {
    Path   p;
    int    i, j, pathchg;
    int    numOnPath, numNotOnPath;
    DTYPE    pathlen;
    int    n = tsp->n;
    double energyChange, T;

    pathlen = pathLength(tsp);

    for (T = T_INIT; T > FINAL_T; T *= COOLING)  /* annealing schedule */ {
        pathchg = 0;
        for (j = 0; j < TRIES_PER_T; j++) {
            do {
                p[0] = unifRand(n);
                p[1] = unifRand(n);
                /* non-empty path */
                if (p[0] == p[1]) p[1] = MOD(p[0]+1, n);
                numOnPath = MOD(p[1]-p[0], n) + 1;
                numNotOnPath = n - numOnPath;
            } while (numOnPath < 2 || numNotOnPath < 2); /* non-empty path */

            if (RANDOM() % 2) /*  threeWay */ {
                do {
                    p[2] = MOD(unifRand(numNotOnPath)+p[1]+1, n);
                } while (p[0] == MOD(p[2]+1, n)); /* avoids a non-change */

                energyChange = getThreeWayCost(tsp, p);
                if (energyChange < 0 || RREAL < exp(-energyChange/T)) {
                    pathchg++;
                    pathlen += energyChange;
                    doThreeWay(tsp, p);
                }
            } else {
                /* path Reverse */
                energyChange = getReverseCost(tsp, p);
                if (energyChange < 0 || RREAL < exp(-energyChange/T)) {
                    pathchg++;
                    pathlen += energyChange;
                    doReverse(tsp, p);
                }
            }
            //  if the new length is better than best then save it as best
            if (pathlen < tsp->bestlen) {
                tsp->bestlen = pathlen;
                for (i = 0; i < tsp->n; i++) tsp->border[i] = tsp->iorder[i];
            }
            if (pathchg > IMPROVED_PATH_PER_T) break; /* finish early */
        }
        PGR_DBG("T:%f L:%f B:%f C:%d", T, pathlen, tsp->bestlen, pathchg);
        if (pathchg == 0) break;   /* if no change then quit */
    }
}
Пример #10
0
static
bool
fetch_column_info(
        Column_info_t *info) {
    PGR_DBG("Fetching column info of %s", info->name);
    info->colNumber =  SPI_fnumber(SPI_tuptable->tupdesc, info->name);
    if (info->strict && !column_found(info->colNumber)) {
        elog(ERROR, "Column '%s' not Found", info->name);
    }
    if (column_found(info->colNumber)) {
        (info->type) = SPI_gettypeid(SPI_tuptable->tupdesc, (info->colNumber));
        if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
            elog(ERROR, "Type of column '%s' not Found", info->name);
        }
        PGR_DBG("Column %s found: %llu", info->name, info->type);
        return true;
    }
    PGR_DBG("Column %s not found", info->name);
    return false;
}
Пример #11
0
static int
finish(int code, int ret)
{
  PGR_DBG("In finish, trying to disconnect from spi %d",ret);
  code = SPI_finish();
  if (code  != SPI_OK_FINISH )
  {
    elog(ERROR,"couldn't disconnect from SPI");
    return -1 ;
  }			
  return ret;
}
Пример #12
0
/*                          MODIFY AS NEEDED                                   */
static
void
process( char* edges_sql,
        int64_t start_vid,
        int64_t *end_vidsArr,
        size_t size_end_vidsArr,
        bool directed,
        MY_RETURN_VALUE_TYPE **result_tuples,
        size_t *result_count) {
    pgr_SPI_connect();

    PGR_DBG("Load data");
    MY_EDGE_TYPE *edges = NULL;
    size_t total_edges = 0;

    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");
        (*result_count) = 0;
        (*result_tuples) = NULL;
        pgr_SPI_finish();
        return;
    }

    PGR_DBG("Starting processing");
    char *err_msg = NULL;
    char *log_msg = NULL;

    // Code standard:
    // Pass the arrays and the sizes on the same line
    clock_t start_t = clock();
    do_pgr_MY_FUNCTION_NAME(
            edges, total_edges,
            start_vid,
            end_vidsArr, size_end_vidsArr,
            directed,
            result_tuples,
            result_count,
            &log_msg,
            &err_msg);
    time_msg(" processing pgr_funnyDijkstra", start_t, clock());

    PGR_DBG("Returning %ld tuples\n", *result_count);
    PGR_DBG("LOG: %s\n", log_msg);
    if (log_msg) free(log_msg);

    if (err_msg) {
        if (*result_tuples) free(*result_tuples);
        if (end_vidsArr) free(end_vidsArr);
        elog(ERROR, "%s", err_msg);
        free(err_msg);
    }

    pfree(edges);
    pgr_SPI_finish();
}
Пример #13
0
/*                          MODIFY AS NEEDED                                  */
static
void
process(
        char* edges_sql,
        int64_t start_vid,
        int64_t end_vid,
        bool directed,
        bool only_cost,
        General_path_element_t **result_tuples,
        size_t *result_count) {
    pgr_SPI_connect();

    PGR_DBG("Load data");
    pgr_edge_t *edges = NULL;

    if (start_vid == end_vid) {
        (*result_count) = 0;
        (*result_tuples) = NULL;
        pgr_SPI_finish();
        return;
    }

    size_t total_tuples = 0;
    pgr_get_edges(edges_sql, &edges, &total_tuples);

    if (total_tuples == 0) {
        PGR_DBG("No edges found");
        (*result_count) = 0;
        (*result_tuples) = NULL;
        pgr_SPI_finish();
        return;
    }
    PGR_DBG("Total %ld tuples in query:", total_tuples);

    PGR_DBG("Starting processing");
    clock_t start_t = clock();
    char *err_msg = NULL;
    do_pgr_one_to_one_dijkstra(
            edges,
            total_tuples,
            start_vid,
            end_vid,
            directed,
            only_cost,
            result_tuples,
            result_count,
            &err_msg);

    time_msg(" processing Dijkstra one to one", start_t, clock());
    PGR_DBG("Returning %ld tuples\n", *result_count);
    PGR_DBG("Returned message = %s\n", err_msg);

    free(err_msg);
    pfree(edges);
    pgr_SPI_finish();
}
Пример #14
0
/*                          MODIFY AS NEEDED                                  */
static
void
process(
    char *edges_sql,
    int64_t *source_vertices, size_t size_source_verticesArr,
    int64_t sink_vertex,
    bool directed,
    General_path_element_t **result_tuples,
    size_t *result_count) {
    pgr_SPI_connect();

    PGR_DBG("Load data");
    pgr_basic_edge_t *edges = NULL;

    size_t total_tuples = 0;

    pgr_get_basic_edges(edges_sql, &edges, &total_tuples);

    if (total_tuples == 0) {
        PGR_DBG("No edges found");
        (*result_count) = 0;
        (*result_tuples) = NULL;
        pgr_SPI_finish();
        return;
    }
    PGR_DBG("Total %ld tuples in query:", total_tuples);

    PGR_DBG("Starting processing");
    clock_t start_t = clock();
    char *err_msg = NULL;
    do_pgr_edge_disjoint_paths_many_to_one(
        edges,
        total_tuples,
        source_vertices,
        size_source_verticesArr,
        sink_vertex,
        directed,
        result_tuples,
        result_count,
        &err_msg);

    time_msg("processing edge disjoint paths", start_t, clock());
    PGR_DBG("Returning %ld tuples\n", *result_count);
    PGR_DBG("Returned message = %s\n", err_msg);

    free(err_msg);
    pfree(edges);
    pgr_SPI_finish();
}
Пример #15
0
/*                          MODIFY AS NEEDED                                  */
static
void
process(
    char *edges_sql,
    bool directed,
    pgr_basic_edge_t **result_tuples,
    size_t *result_count) {
    pgr_SPI_connect();

    PGR_DBG("Load data");
    pgr_basic_edge_t *edges = NULL;

    size_t total_tuples = 0;

    pgr_get_basic_edges(edges_sql, &edges, &total_tuples);

    if (total_tuples == 0) {
        PGR_DBG("No edges found");
        (*result_count) = 0;
        (*result_tuples) = NULL;
        pgr_SPI_finish();
        return;
    }
    PGR_DBG("Total %ld tuples in query:", total_tuples);

    PGR_DBG("Starting processing");
    clock_t start_t = clock();
    char *err_msg = NULL;
    do_pgr_maximum_cardinality_matching(
        edges,
        directed,
        total_tuples,
        result_tuples,
        result_count,
        &err_msg);

    time_msg("processing max flow", start_t, clock());
    PGR_DBG("Returning %ld tuples\n", *result_count);
    PGR_DBG("Returned message = %s\n", err_msg);

    free(err_msg);
    pfree(edges);
    pgr_SPI_finish();
}
Пример #16
0
/*                          MODIFY AS NEEDED                                  */
static
void
process(
        char* distances_sql,
        int64_t start_vid,
        int64_t end_vid,
        General_path_element_t **result_tuples,
        size_t *result_count) {
    pgr_SPI_connect();

    PGR_DBG("Load data");
    Matrix_cell_t *distances = NULL;
    size_t total_distances = 0;
    pgr_get_distances(distances_sql, &distances, &total_distances);

    if (total_distances == 0) {
        PGR_DBG("No distances found");
        (*result_count) = 0;
        (*result_tuples) = NULL;
        pgr_SPI_finish();
        return;
    }
    PGR_DBG("Total %ld tuples in query:", total_distances);

    PGR_DBG("Starting processing");
    char *err_msg = NULL;
    do_pgr_tsp(
            distances,
            total_distances,
            start_vid,
            end_vid,
            result_tuples,
            result_count,
            &err_msg);
    PGR_DBG("Returning %ld tuples\n", *result_count);
    PGR_DBG("Returned message = %s\n", err_msg);

    free(err_msg);
    pfree(distances);
    pgr_SPI_finish();
}
Пример #17
0
/*                          MODIFY AS NEEDED                                  */
static
void process(
        char* edges_sql,
        bool directed,
        Matrix_cell_t **result_tuples,
        size_t *result_count) {
    pgr_SPI_connect();

    PGR_DBG("Load data");
    pgr_edge_t *edges = NULL;
    size_t total_tuples = 0;
    pgr_get_data_4_columns(edges_sql, &edges, &total_tuples);

    if (total_tuples == 0) {
        PGR_DBG("No edges found");
        (*result_count) = 0;
        (*result_tuples) = NULL;
        pgr_SPI_finish();
        return;
    }
    PGR_DBG("Total %ld tuples in query:", total_tuples);

    PGR_DBG("Starting processing");
    char *err_msg = (char *)"";
    clock_t start_t = clock();
    do_pgr_johnson(
            edges,
            total_tuples,
            directed,
            result_tuples,
            result_count,
            &err_msg);
    time_msg(" processing Johnson", start_t, clock());
    PGR_DBG("Returning %ld tuples\n", *result_count);
    PGR_DBG("Returned message = %s\n", err_msg);

    free(err_msg);
    pfree(edges);
    pgr_SPI_finish();
}
Пример #18
0
Datum
#else  // _MSC_VER
PGDLLEXPORT Datum
#endif
johnson(PG_FUNCTION_ARGS) {
    FuncCallContext     *funcctx;
    uint32_t              call_cntr;
    uint32_t               max_calls;
    TupleDesc            tuple_desc;

    /**************************************************************************/
    /*                          MODIFY AS NEEDED                              */
    /*                                                                        */
    Matrix_cell_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_johnson(
        // edges_sql TEXT,
        // directed BOOLEAN,

        PGR_DBG("Calling process");
        process(
                pgr_text2char(PG_GETARG_TEXT_P(0)),
                PG_GETARG_BOOL(1),
                &result_tuples,
                &result_count);

        /*                                                                   */
        /*********************************************************************/

        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 = (Matrix_cell_t*) funcctx->user_fctx;

    if (call_cntr < max_calls) {
        HeapTuple    tuple;
        Datum        result;
        Datum        *values;
        bool*        nulls;

        /*********************************************************************/
        /*                          MODIFY AS NEEDED                         */
        // OUT seq BIGINT,
        // OUT from_vid BIGINT,
        // OUT to_vid BIGINT,
        // OUT cost float)

        values = palloc(3 * sizeof(Datum));
        nulls = palloc(3 * sizeof(bool));

        // postgres starts counting from 1
        values[0] = Int64GetDatum(result_tuples[call_cntr].from_vid);
        nulls[0] = false;
        values[1] = Int64GetDatum(result_tuples[call_cntr].to_vid);
        nulls[1] = false;
        values[2] = Float8GetDatum(result_tuples[call_cntr].cost);
        nulls[2] = false;

        /*********************************************************************/

        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);
    }
}
Пример #19
0
static
void
process(char* edges_sql,
        int64_t start_vid,
        int64_t end_vid,
        bool directed,
        int heuristic,
        double factor,
        double epsilon,
        bool only_cost,
        General_path_element_t **result_tuples,
        size_t *result_count) {
    check_parameters(heuristic, factor, epsilon);

    pgr_SPI_connect();

    PGR_DBG("Load data");
    Pgr_edge_xy_t *edges = NULL;
    size_t total_edges = 0;

    pgr_get_edges_xy(edges_sql, &edges, &total_edges);
    PGR_DBG("Total %ld edges in query:", total_edges);

    if (total_edges == 0) {
        PGR_DBG("No edges found");
        (*result_count) = 0;
        (*result_tuples) = NULL;
        pgr_SPI_finish();
        return;
    }

    PGR_DBG("Starting processing");
    char* log_msg = NULL;
    char* notice_msg = NULL;
    char* err_msg = NULL;
    clock_t start_t = clock();
    do_pgr_astarManyToMany(
            edges, total_edges,
            &start_vid, 1,
            &end_vid, 1,
            directed,
            heuristic,
            factor,
            epsilon,
            only_cost,
            true,
            result_tuples,
            result_count,
            &log_msg,
            &notice_msg,
            &err_msg);

    if (only_cost) {
        time_msg("processing pgr_astarCost(one to one)", start_t, clock());
    } else {
        time_msg("processing pgr_astar(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 (log_msg) pfree(log_msg);
    if (notice_msg) pfree(notice_msg);
    if (err_msg) pfree(err_msg);
    if (edges) pfree(edges);

    pgr_SPI_finish();
}
Datum
#else  // _MSC_VER
PGDLLEXPORT Datum
#endif
one_to_one_withPoints(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 = 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                                   */
        // CREATE OR REPLACE FUNCTION pgr_withPoint(
        // edges_sql TEXT,
        // points_sql TEXT,
        // start_pid BIGINT,
        // end_pid BIGINT,
        // directed BOOLEAN -- DEFAULT true,
        // driving_side CHAR -- DEFAULT 'b',
        // details BOOLEAN -- DEFAULT true,
        // only_cost BOOLEAN DEFAULT false,

        PGR_DBG("Calling process");
        PGR_DBG("initial driving side:%s", pgr_text2char(PG_GETARG_TEXT_P(5)));
        process(
                pgr_text2char(PG_GETARG_TEXT_P(0)),
                pgr_text2char(PG_GETARG_TEXT_P(1)),
                PG_GETARG_INT64(2),
                PG_GETARG_INT64(3),
                PG_GETARG_BOOL(4),
                pgr_text2char(PG_GETARG_TEXT_P(5)),
                PG_GETARG_BOOL(6),
                PG_GETARG_BOOL(7),
                &result_tuples,
                &result_count);
        /*                                                                             */
        /*******************************************************************************/

        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;
        char*        nulls;

        /*******************************************************************************/
        /*                          MODIFY AS NEEDED                                   */
        // OUT seq BIGINT,
        // OUT path_seq,
        // OUT node BIGINT,
        // OUT edge BIGINT,
        // OUT cost FLOAT,
        // OUT agg_cost FLOAT)


        values = palloc(6 * sizeof(Datum));
        nulls = palloc(6 * sizeof(char));

        size_t i;
        for(i = 0; i < 6; ++i) {
            nulls[i] = ' ';
        }


        // 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].node);
        values[3] = Int64GetDatum(result_tuples[call_cntr].edge);
        values[4] = Float8GetDatum(result_tuples[call_cntr].cost);
        values[5] = Float8GetDatum(result_tuples[call_cntr].agg_cost);
        /*******************************************************************************/

        tuple = heap_formtuple(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,
        char* points_sql,
        int64_t start_pid,
        int64_t end_pid,
        bool directed,
        char *driving_side,
        bool details,
        bool only_cost,
        General_path_element_t **result_tuples,
        size_t *result_count) {

    driving_side[0] = tolower(driving_side[0]);
    PGR_DBG("driving side:%c",driving_side[0]);
    if (! ((driving_side[0] == 'r')
                || (driving_side[0] == 'l'))) {
        driving_side[0] = 'b'; 
    }
    PGR_DBG("estimated driving side:%c",driving_side[0]);

    pgr_SPI_connect();

    PGR_DBG("load the points");
    Point_on_edge_t *points = NULL;
    size_t total_points = 0;
    pgr_get_points(points_sql, &points, &total_points);

#ifdef DEBUG
    size_t i = 0;
    for (i = 0; i < total_points; i ++) {
       PGR_DBG("%ld\t%ld\t%f\t%c",points[i].pid, points[i].edge_id, points[i].fraction, points[i].side);
    }
#endif

    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_data_5_columns(edges_of_points_query, &edges_of_points, &total_edges_of_points);

    PGR_DBG("Total %ld edges in query:", total_edges_of_points);
#ifdef DEBUG
    for (i = 0; i < total_edges_of_points; i ++) {
        PGR_DBG("%ld\t%ld\t%ld\t%f\t%f",
                edges_of_points[i].id,
                edges_of_points[i].source,
                edges_of_points[i].target,
                edges_of_points[i].cost,
                edges_of_points[i].reverse_cost);
    }
#endif



    PGR_DBG("load the edges that dont match the points");
    pgr_edge_t *edges = NULL;
    size_t total_edges = 0;
    pgr_get_data_5_columns(edges_no_points_query, &edges, &total_edges);

    PGR_DBG("Total %ld edges in query:", total_edges);
#ifdef DEBUG
    for (i = 0; i < total_edges; i ++) {
        PGR_DBG("%ld\t%ld\t%ld\t%f\t%f",
                edges[i].id,
                edges[i].source,
                edges[i].target,
                edges[i].cost,
                edges[i].reverse_cost);
    }
#endif

    PGR_DBG("freeing allocated memory not used anymore");
    free(edges_of_points_query);
    free(edges_no_points_query);

    if ( (total_edges + total_edges_of_points) == 0) {
        PGR_DBG("No edges found");
        (*result_count) = 0;
        (*result_tuples) = NULL;
        pgr_SPI_finish();
        return;
    }

    PGR_DBG("Starting processing");
    char *err_msg = NULL;
    clock_t start_t = clock();
    int errcode = do_pgr_withPoints(
            edges,
            total_edges,
            points,
            total_points,
            edges_of_points,
            total_edges_of_points,
            start_pid,
            end_pid,
            directed,
            driving_side[0],
            details,
            only_cost,
            result_tuples,
            result_count,
            &err_msg);
    time_msg(" processing withPoints one to one", start_t, clock());
    PGR_DBG("Returning %ld tuples\n", *result_count);
    PGR_DBG("Returned message = %s\n", err_msg);

    if (!err_msg) free(err_msg);
    pfree(edges);
    pgr_SPI_finish();

    if (errcode) {
        pgr_send_error(errcode);
    }

}
Пример #22
0
PGDLLEXPORT Datum
one_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 BIGINT,
        // end_vid BIGINT,
        // directed BOOLEAN default true,

        PGR_DBG("Calling process");
        process(
                pgr_text2char(PG_GETARG_TEXT_P(0)),
                PG_GETARG_INT64(1),
                PG_GETARG_INT64(2),
                PG_GETARG_BOOL(3),
                PG_GETARG_BOOL(4),
                &result_tuples,
                &result_count);

        /*                                                                    */
        /**********************************************************************/

        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                          */
        // 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(call_cntr + 1);
        values[1] = Int32GetDatum(result_tuples[call_cntr].seq);
        values[2] = Int64GetDatum(result_tuples[call_cntr].node);
        values[3] = Int64GetDatum(result_tuples[call_cntr].edge);
        values[4] = Float8GetDatum(result_tuples[call_cntr].cost);
        values[5] = 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);
    }
}
Пример #23
0
/*                          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,
            &notice_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();
}
Пример #24
0
/*                          MODIFY AS NEEDED                                   */
static
void
process(
        char* edges_sql,
        char* points_sql,
        int64_t start_pid,
        int64_t end_pid,
        int k,

        bool directed,
        bool heap_paths,
        char *driving_side,
        bool details,

        General_path_element_t **result_tuples,
        size_t *result_count) {

    driving_side[0] = (char) tolower(driving_side[0]);
    PGR_DBG("driving side:%c",driving_side[0]);
    if (! ((driving_side[0] == 'r')
                || (driving_side[0] == 'l'))) {
        driving_side[0] = 'b'; 
    }

    pgr_SPI_connect();

    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);

    PGR_DBG("freeing allocated memory not used anymore");
    free(edges_of_points_query);
    free(edges_no_points_query);

    if ((total_edges + total_edges_of_points) == 0) {
        PGR_DBG("No edges found");
        (*result_count) = 0;
        (*result_tuples) = NULL;
        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_withPointsKsp(
            edges,
            total_edges,
            points,
            total_points,
            edges_of_points,
            total_edges_of_points,
            start_pid,
            end_pid,
            k,

            directed,
            heap_paths,
            driving_side[0],
            details,

            result_tuples,
            result_count,

            &log_msg,
            &notice_msg,
            &err_msg);
    time_msg(" processing withPointsKSP", start_t, clock());

    PGR_DBG("Returned message = %s\n", err_msg);

    if (err_msg) {
        if (*result_tuples) free(*result_tuples);
    }
    pgr_global_report(log_msg, notice_msg, err_msg);

    pfree(edges);
    pfree(edges_of_points);
    pfree(points);

    pgr_SPI_finish();

}
Пример #25
0
/*!
 * bigint start_vid,
 * bigint end_vid,
 * float agg_cost,
 */
void pgr_get_matrixRows(
        char *sql,
        Matrix_cell_t **rows,
        size_t *total_rows) {
    clock_t start_t = clock();

    const int tuple_limit = 1000000;

    size_t ntuples;
    size_t total_tuples = 0;

    Column_info_t info[3];

    int i;
    for (i = 0; i < 3; ++i) {
        info[i].colNumber = -1;
        info[i].type = 0;
        info[i].strict = true;
        info[i].eType = ANY_INTEGER;
    }
    info[0].name = strdup("start_vid");
    info[1].name = strdup("end_vid");
    info[2].name = strdup("agg_cost");

    info[2].eType = ANY_NUMERICAL;


    void *SPIplan;
    SPIplan = pgr_SPI_prepare(sql);

    Portal SPIportal;
    SPIportal = pgr_SPI_cursor_open(SPIplan);


    bool moredata = TRUE;
    (*total_rows) = total_tuples;

    while (moredata == TRUE) {
        SPI_cursor_fetch(SPIportal, TRUE, tuple_limit);
        if (total_tuples == 0)
            pgr_fetch_column_info(info, 3);

        ntuples = SPI_processed;
        total_tuples += ntuples;

        if (ntuples > 0) {
            if ((*rows) == NULL)
                (*rows) = (Matrix_cell_t *)palloc0(
                        total_tuples * sizeof(Matrix_cell_t));
            else
                (*rows) = (Matrix_cell_t *)repalloc(
                        (*rows), total_tuples * sizeof(Matrix_cell_t));

            if ((*rows) == NULL) {
                elog(ERROR, "Out of memory");
            }

            SPITupleTable *tuptable = SPI_tuptable;
            TupleDesc tupdesc = SPI_tuptable->tupdesc;
            PGR_DBG("processing %ld edge tupĺes", ntuples);

            size_t t;
            for (t = 0; t < ntuples; t++) {
                HeapTuple tuple = tuptable->vals[t];
                pgr_fetch_row(&tuple, &tupdesc, info,
                        &(*rows)[total_tuples - ntuples + t]);
            }
            SPI_freetuptable(tuptable);
        } else {
            moredata = FALSE;
        }
    }

    SPI_cursor_close(SPIportal);


    if (total_tuples == 0) {
        (*total_rows) = 0;
        PGR_DBG("NO rows");
        return;
    }

    (*total_rows) = total_tuples;
    time_msg(" reading Edges", start_t, clock());
}
Пример #26
0
PGDLLEXPORT Datum withPoints_ksp(PG_FUNCTION_ARGS) {
    FuncCallContext     *funcctx;
    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_withPoint(
        // edges_sql TEXT,
        // points_sql TEXT,
        // start_pid INTEGER,
        // end_pid BIGINT,
        // k BIGINT,
        //
        // directed BOOLEAN -- DEFAULT true,
        // heap_paths BOOLEAN -- DEFAULT false,
        // driving_side CHAR -- DEFAULT 'b',
        // details BOOLEAN -- DEFAULT false,

        PGR_DBG("Calling process");
        PGR_DBG("initial driving side:%s", text_to_cstring(PG_GETARG_TEXT_P(7)));
        process(
                text_to_cstring(PG_GETARG_TEXT_P(0)),
                text_to_cstring(PG_GETARG_TEXT_P(1)),
                PG_GETARG_INT64(2),
                PG_GETARG_INT64(3),
                PG_GETARG_INT32(4),
                PG_GETARG_BOOL(5),
                PG_GETARG_BOOL(6),
                text_to_cstring(PG_GETARG_TEXT_P(7)),
                PG_GETARG_BOOL(8),
                &result_tuples,
                &result_count);

        /*                                                                             */
        /*******************************************************************************/

#if PGSQL_VERSION > 95
        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                                   */
        values = palloc(7 * sizeof(Datum));
        nulls = palloc(7 * sizeof(bool));

        size_t i;
        for(i = 0; i < 7; ++i) {
            nulls[i] = false;
        }

        /*
           OUT seq INTEGER, OUT path_id INTEGER, OUT path_seq INTEGER,
           OUT node BIGINT, OUT edge BIGINT,
           OUT cost FLOAT, OUT agg_cost FLOAT)
           */


        // postgres starts counting from 1
        values[0] = Int32GetDatum(funcctx->call_cntr + 1);
        values[1] = Int32GetDatum((int)(result_tuples[funcctx->call_cntr].start_id + 1));
        values[2] = Int32GetDatum(result_tuples[funcctx->call_cntr].seq);
        values[3] = Int64GetDatum(result_tuples[funcctx->call_cntr].node);
        values[4] = Int64GetDatum(result_tuples[funcctx->call_cntr].edge);
        values[5] = Float8GetDatum(result_tuples[funcctx->call_cntr].cost);
        values[6] = 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 {
        SRF_RETURN_DONE(funcctx);
    }
}
Пример #27
0
static
void compute(
        char* edges_sql,
        int64_t start_vertex,
        int64_t end_vertex,
        int k,
        bool directed,
        bool heap_paths,
        General_path_element_t **result_tuples, size_t *result_count) {
    pgr_SPI_connect();

    PGR_DBG("Load data");
    pgr_edge_t *edges = NULL;
    size_t total_edges = 0;


    if (start_vertex == end_vertex) {
        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("Calling do_pgr_ksp\n");
    PGR_DBG("heap_paths = %i\n", heap_paths);

    clock_t start_t = clock();
    char *log_msg = NULL;
    char *notice_msg = NULL;
    char *err_msg = NULL;

    do_pgr_ksp(
            edges,
            total_edges,
            start_vertex,
            end_vertex,
            k,
            directed,
            heap_paths,
            result_tuples,
            result_count,
            &log_msg,
            &notice_msg,
            &err_msg);
    time_msg(" processing KSP", start_t, clock());

    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_global_report(log_msg, notice_msg, err_msg);

    pfree(edges);
    pgr_SPI_finish();
}
Пример #28
0
PGDLLEXPORT Datum
kshortest_path(PG_FUNCTION_ARGS) {
    FuncCallContext     *funcctx;
    TupleDesc            tuple_desc;
    General_path_element_t      *path = NULL;
    size_t result_count = 0;

    if (SRF_IS_FIRSTCALL()) {
        MemoryContext   oldcontext;
        funcctx = SRF_FIRSTCALL_INIT();
        oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);


        /*
           CREATE OR REPLACE FUNCTION _pgr_ksp(
           sql text,
           start_vid bigint,
           end_vid bigint,
           k integer,
           directed boolean,
           heap_paths boolean
           */
        PGR_DBG("Calling process");
        compute(
                text_to_cstring(PG_GETARG_TEXT_P(0)),
                PG_GETARG_INT64(1),
                PG_GETARG_INT64(2),
                PG_GETARG_INT32(3),
                PG_GETARG_BOOL(4),
                PG_GETARG_BOOL(5),
                &path,
                &result_count);
        PGR_DBG("Total number of tuples to be returned %ld \n", result_count);


#if PGSQL_VERSION > 95
        funcctx->max_calls = result_count;
#else
        funcctx->max_calls = (uint32_t)result_count;
#endif
        funcctx->user_fctx = 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\n")));

        funcctx->tuple_desc = tuple_desc;
        MemoryContextSwitchTo(oldcontext);
    }


    funcctx = SRF_PERCALL_SETUP();


    tuple_desc = funcctx->tuple_desc;
    path = (General_path_element_t*) funcctx->user_fctx;

    if (funcctx->call_cntr < funcctx->max_calls) {
        HeapTuple    tuple;
        Datum        result;
        Datum *values;
        bool* nulls;

        values = palloc(7 * sizeof(Datum));
        nulls = palloc(7 * sizeof(bool));


        size_t i;
        for (i = 0; i < 7; ++i) {
            nulls[i] = false;
        }

        values[0] = Int32GetDatum(funcctx->call_cntr + 1);
        values[1] = Int32GetDatum(path[funcctx->call_cntr].start_id + 1);
        values[2] = Int32GetDatum(path[funcctx->call_cntr].seq);
        values[3] = Int64GetDatum(path[funcctx->call_cntr].node);
        values[4] = Int64GetDatum(path[funcctx->call_cntr].edge);
        values[5] = Float8GetDatum(path[funcctx->call_cntr].cost);
        values[6] = Float8GetDatum(path[funcctx->call_cntr].agg_cost);

        tuple = heap_form_tuple(tuple_desc, values, nulls);
        result = HeapTupleGetDatum(tuple);
        SRF_RETURN_NEXT(funcctx, result);
    } else {   /* do when there is no more left */
        SRF_RETURN_DONE(funcctx);
    }
}
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);
  }
}
Пример #30
0
PGDLLEXPORT Datum
maximum_cardinality_matching(PG_FUNCTION_ARGS) {
    FuncCallContext *funcctx;
    uint32_t call_cntr;
    uint32_t max_calls;
    TupleDesc tuple_desc;

    /**************************************************************************/
    /*                          MODIFY AS NEEDED                              */
    /*                                                                        */
    pgr_basic_edge_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                          */
        PGR_DBG("Calling process");
        process(
            pgr_text2char(PG_GETARG_TEXT_P(0)),
            PG_GETARG_BOOL(1),
            &result_tuples,
            &result_count);

        /*                                                                    */
        /**********************************************************************/

        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 = (pgr_basic_edge_t *) funcctx->user_fctx;

    if (call_cntr < max_calls) {
        HeapTuple tuple;
        Datum result;
        Datum *values;
        bool *nulls;

        /**********************************************************************/
        /*                          MODIFY AS NEEDED                          */

        values = palloc(4 * sizeof(Datum));
        nulls = palloc(4 * sizeof(bool));


        size_t i;
        for (i = 0; i < 4; ++i) {
            nulls[i] = false;
        }

        // postgres starts counting from 1
        values[0] = Int32GetDatum(call_cntr + 1);
        values[1] = Int64GetDatum(result_tuples[call_cntr].edge_id);
        values[2] = Int64GetDatum(result_tuples[call_cntr].source);
        values[3] = Int64GetDatum(result_tuples[call_cntr].target);
        /**********************************************************************/

        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);
    }
}