Exemple #1
0
static int compute_shortest_path_shooting_star(char* sql, int source_edge_id, 
				       int target_edge_id, bool directed, 
				       bool has_reverse_cost, 
				       path_element_t **path, int *path_count) 
{
  
  int SPIcode;
  void *SPIplan;
  Portal SPIportal;
  bool moredata = TRUE;
  int ntuples;
  edge_shooting_star_t *edges = NULL;
  int total_tuples = 0;
  
//  int v_max_id=0;
//  int v_min_id=INT_MAX;  
  int e_max_id=0;
  int e_min_id=INT_MAX;  
    
  edge_shooting_star_columns_t edge_columns = {id: -1, source: -1, target: -1, 
				       cost: -1, reverse_cost: -1, 
				       s_x: -1, s_y: -1, t_x: -1, t_y: -1,
				       to_cost: -1, rule: -1};
  char *err_msg;
  int ret = -1;
  register int z, t;
  
  int s_count=0;
  int t_count=0;
  
  DBG("start shortest_path_shooting_star\n");
        
  SPIcode = SPI_connect();
  if (SPIcode  != SPI_OK_CONNECT)
    {
      elog(ERROR, "shortest_path_shooting_star: couldn't open a connection to SPI");
      return -1;
    }

  SPIplan = SPI_prepare(sql, 0, NULL);
  if (SPIplan  == NULL)
    {
      elog(ERROR, "shortest_path_shooting_star: couldn't create query plan via SPI");
      return -1;
    }

  if ((SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true)) == NULL) 
    {
      elog(ERROR, "shortest_path_shooting_star: SPI_cursor_open('%s') returns NULL", 
	   sql);
      return -1;
    }

  while (moredata == TRUE)
    {
      SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);

      if (edge_columns.id == -1) 
        {
	  if (fetch_edge_shooting_star_columns(SPI_tuptable, &edge_columns, 
				       has_reverse_cost) == -1)
	    return finish(SPIcode, ret);
        }
	
	//DBG("***%i***", ret);

      ntuples = SPI_processed;
      total_tuples += ntuples;

      if (!edges)
	edges = palloc(total_tuples * sizeof(edge_shooting_star_t));
      else
	edges = repalloc(edges, total_tuples * sizeof(edge_shooting_star_t));

      if (edges == NULL) 
        {
	  elog(ERROR, "Out of memory");
	  return finish(SPIcode, ret);
        }

      if (ntuples > 0) 
        {
	  int t;
	  SPITupleTable *tuptable = SPI_tuptable;
	  TupleDesc tupdesc = SPI_tuptable->tupdesc;
	  
	  for (t = 0; t < ntuples; t++) 
            {
	      HeapTuple tuple = tuptable->vals[t];
	      fetch_edge_shooting_star(&tuple, &tupdesc, &edge_columns, 
			       &edges[total_tuples - ntuples + t]);
            }
	  SPI_freetuptable(tuptable);
        } 
      else 
        {
	  moredata = FALSE;
        }
    }
    
      
  DBG("Total %i tuples", total_tuples);

    

  for(z=0; z<total_tuples; z++)
  {
    if(edges[z].id<e_min_id)
      e_min_id=edges[z].id;

    if(edges[z].id>e_max_id)
      e_max_id=edges[z].id;

  }

    DBG("E : %i <-> %i", e_min_id, e_max_id);

  for(z=0; z<total_tuples; ++z)
  {

    //check if edges[] contains source and target
    if(edges[z].id == source_edge_id)
      ++s_count;
    if(edges[z].id == target_edge_id)
      ++t_count;


    //edges[z].source-=v_min_id;
    //edges[z].target-=v_min_id;
    
  }
    
  DBG("Total %i tuples", total_tuples);

  if(s_count == 0)
  {
    elog(ERROR, "Start edge was not found.");
    return -1;
  }
	      
  if(t_count == 0)
  {
    elog(ERROR, "Target edge was not found.");
    return -1;
  }
			    
  DBG("Total %i tuples", total_tuples);

  DBG("Calling boost_shooting_star <%i>\n", total_tuples);

  //time_t stime = time(NULL);    

  ret = boost_shooting_star(edges, total_tuples, source_edge_id, 
		    target_edge_id,
		    directed, has_reverse_cost,
		    path, path_count, &err_msg, e_max_id);

  //time_t etime = time(NULL);    

  //DBG("Path was calculated in %f seconds. \n", difftime(etime, stime));

  DBG("SIZE %i\n",*path_count);

  DBG("ret =  %i\n",ret);
  

  if (ret < 0)
    {
      ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED), 
        errmsg("Error computing path: %s", err_msg)));
    } 
  return finish(SPIcode, ret);
}


PG_FUNCTION_INFO_V1(shortest_path_shooting_star);
Datum
shortest_path_shooting_star(PG_FUNCTION_ARGS)
{
  FuncCallContext     *funcctx;
  int                  call_cntr;
  int                  max_calls;
  TupleDesc            tuple_desc;
  path_element_t      *path = 0;
  
  /* stuff done only on the first call of the function */
  if (SRF_IS_FIRSTCALL())
    {
      MemoryContext   oldcontext;
      int path_count = 0;
      int ret;

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


      ret = compute_shortest_path_shooting_star(text2char(PG_GETARG_TEXT_P(0)),
					PG_GETARG_INT32(1),
					PG_GETARG_INT32(2),
					PG_GETARG_BOOL(3),
					PG_GETARG_BOOL(4), 
					&path, &path_count);

#ifdef DEBUG
      DBG("Ret is %i", ret);
      if (ret >= 0) 
        {
	  int i;
	  for (i = 0; i < path_count; i++) 
            {
	      DBG("Step # %i vertex_id  %i ", i, path[i].vertex_id);
	      DBG("        edge_id    %i ", path[i].edge_id);
	      DBG("        cost       %f ", path[i].cost);
            }
        }
#endif

      /* total number of tuples to be returned */
      DBG("Conting tuples number\n");
      funcctx->max_calls = path_count;
      funcctx->user_fctx = path;
      
      DBG("Path count %i", path_count);
      
      funcctx->tuple_desc = 
	BlessTupleDesc(RelationNameGetTupleDesc("pgr_costResult"));

      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;
  path = (path_element_t*) funcctx->user_fctx;
  
  DBG("Trying to allocate some memory\n");

  if (call_cntr < max_calls)    /* do when there is more left to send */
    {
      HeapTuple    tuple;
      Datum        result;
      Datum *values;
      char* nulls;
      
      values = palloc(4 * sizeof(Datum));
      nulls = palloc(4 * sizeof(char));
  
      values[0] = Int32GetDatum(call_cntr);
      nulls[0] = ' ';
      values[1] = Int32GetDatum(path[call_cntr].vertex_id);
      nulls[1] = ' ';
      values[2] = Int32GetDatum(path[call_cntr].edge_id);
      nulls[2] = ' ';
      values[3] = Float8GetDatum(path[call_cntr].cost);
      nulls[3] = ' ';
  
      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 (path) free(path);
      SRF_RETURN_DONE(funcctx);
    }
}
static void
grab_ExecutorEnd(QueryDesc * queryDesc)
{
	Datum           values[10];
	bool            nulls[10] = {false, false, false, false, false, false, false, false, false, false};
	Relation        dump_heap;
	RangeVar       *dump_table_rv;
	HeapTuple       tuple;
	Oid             namespaceId;

	/* lookup schema */
	namespaceId = GetSysCacheOid1(NAMESPACENAME, CStringGetDatum(EXTENSION_SCHEMA));
	if (OidIsValid(namespaceId)) {
		/* lookup table */
		if (OidIsValid(get_relname_relid(EXTENSION_LOG_TABLE, namespaceId))) {

			/* get table heap */
			dump_table_rv = makeRangeVar(EXTENSION_SCHEMA, EXTENSION_LOG_TABLE, -1);
			dump_heap = heap_openrv(dump_table_rv, RowExclusiveLock);

			/* transaction info */
			values[0] = Int32GetDatum(GetCurrentTransactionId());
			values[1] = Int32GetDatum(GetCurrentCommandId(false));
			values[2] = Int32GetDatum(MyProcPid);
			values[3] = Int32GetDatum(GetUserId());

			/* query timing */
			if (queryDesc->totaltime != NULL) {
				InstrEndLoop(queryDesc->totaltime);
				values[4] = TimestampGetDatum(
							      TimestampTzPlusMilliseconds(GetCurrentTimestamp(),
				  (queryDesc->totaltime->total * -1000.0)));
				values[5] = Float8GetDatum(queryDesc->totaltime->total);
			} else {
				nulls[4] = true;
				nulls[5] = true;
			}

			/* query command type */
			values[6] = Int32GetDatum(queryDesc->operation);

			/* query text */
			values[7] = CStringGetDatum(
				    cstring_to_text(queryDesc->sourceText));

			/* query params */
			if (queryDesc->params != NULL) {
				int             numParams = queryDesc->params->numParams;
				Oid             out_func_oid, ptype;
				Datum           pvalue;
				bool            isvarlena;
				FmgrInfo       *out_functions;

				bool            arr_nulls[numParams];
				size_t          arr_nelems = (size_t) numParams;
				Datum          *arr_val_elems = palloc(sizeof(Datum) * arr_nelems);
				Datum          *arr_typ_elems = palloc(sizeof(Datum) * arr_nelems);
				char            elem_val_byval, elem_val_align, elem_typ_byval,
				                elem_typ_align;
				int16           elem_val_len, elem_typ_len;
				int             elem_dims[1], elem_lbs[1];

				int paramno;

				/* init */
				out_functions = (FmgrInfo *) palloc(
					    (numParams) * sizeof(FmgrInfo));
				get_typlenbyvalalign(TEXTOID, &elem_val_len, &elem_val_byval, &elem_val_align);
				get_typlenbyvalalign(REGTYPEOID, &elem_typ_len, &elem_typ_byval, &elem_typ_align);
				elem_dims[0] = arr_nelems;
				elem_lbs[0] = 1;

				for (paramno = 0; paramno < numParams; paramno++) {
					pvalue = queryDesc->params->params[paramno].value;
					ptype = queryDesc->params->params[paramno].ptype;
					getTypeOutputInfo(ptype, &out_func_oid, &isvarlena);
					fmgr_info(out_func_oid, &out_functions[paramno]);

					arr_typ_elems[paramno] = ptype;

					arr_nulls[paramno] = true;
					if (!queryDesc->params->params[paramno].isnull) {
						arr_nulls[paramno] = false;
						arr_val_elems[paramno] = PointerGetDatum(
							    cstring_to_text(
									    OutputFunctionCall(&out_functions[paramno], pvalue)));
					}
				}
				values[8] = PointerGetDatum(
							 construct_md_array(
							      arr_val_elems,
								  arr_nulls,
									  1,
								  elem_dims,
								   elem_lbs,
								    TEXTOID,
							       elem_val_len,
							     elem_val_byval,
							   elem_val_align));
				values[9] = PointerGetDatum(
							    construct_array(
							      arr_typ_elems,
								 arr_nelems,
								 REGTYPEOID,
							       elem_typ_len,
							     elem_typ_byval,
							   elem_typ_align));

				pfree(out_functions);
				pfree(arr_val_elems);

			} else {
				nulls[8] = true;
				nulls[9] = true;
			}

			/* insert */
			tuple = heap_form_tuple(dump_heap->rd_att, values, nulls);
			simple_heap_insert(dump_heap, tuple);
			heap_close(dump_heap, RowExclusiveLock);
		}
	}
	if (prev_ExecutorEnd)
		prev_ExecutorEnd(queryDesc);
	else
		standard_ExecutorEnd(queryDesc);
}
Exemple #3
0
static Datum
leftmostvalue_float8(void)
{
	return Float8GetDatum(-get_float8_infinity());
}
Exemple #4
0
PGDLLEXPORT Datum
kshortest_path(PG_FUNCTION_ARGS) {
    FuncCallContext     *funcctx;
    TupleDesc            tuple_desc;
    General_path_element_t      *path = NULL;
    size_t result_count = 0;

    /* stuff done only on the first call of the function */
    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)), /* SQL  */
                PG_GETARG_INT64(1),   /* start_vid */
                PG_GETARG_INT64(2),   /* end_vid */
                PG_GETARG_INT32(3),   /* k */
                PG_GETARG_BOOL(4),    /* directed */
                PG_GETARG_BOOL(5),    /* heap_paths */
                &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) {   /* do when there is more left to send */
        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
dijkstra_1_to_many(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* targetsArr;
      int num;

      targetsArr = (int64_t*) pgr_get_bigIntArray(&num, PG_GETARG_ARRAYTYPE_P(2));
      PGR_DBG("targetsArr size %d ", num);


#ifdef DEBUG
      int i;
      for (i = 0; i < num; ++i) {
        PGR_DBG("targetsArr[%d]=%li", i, targetsArr[i]);
      }
#endif

      PGR_DBG("Calling dijkstra_1_to_many_driver");
      dijkstra_1_to_many_driver(
               pgr_text2char(PG_GETARG_TEXT_P(0)),
               PG_GETARG_INT64(1),
               targetsArr, num,
               PG_GETARG_BOOL(3),
               PG_GETARG_BOOL(4), &ret_path, &path_count);

      free(targetsArr);

      /* 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(7 * sizeof(Datum));
      nulls = palloc(7 * sizeof(char));
      // id, start_v, node, edge, cost, tot_cost
      values[0] = Int32GetDatum(call_cntr + 1);
      nulls[0] = ' ';
      values[1] = Int32GetDatum(ret_path[call_cntr].seq);
      nulls[1] = ' ';
      values[2] = Int64GetDatum(ret_path[call_cntr].to);
      nulls[2] = ' ';
      values[3] = Int64GetDatum(ret_path[call_cntr].vertex);
      nulls[3] = ' ';
      values[4] = Int64GetDatum(ret_path[call_cntr].edge);
      nulls[4] = ' ';
      values[5] = Float8GetDatum(ret_path[call_cntr].cost);
      nulls[5] = ' ';
      values[6] = Float8GetDatum(ret_path[call_cntr].tot_cost);
      nulls[6] = ' ';

      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);
  }
}
/**
 * @brief Sets the current state of the engine
 *
 * All this function does is calling the backend's seed functions.
 */
inline
void
NativeRandomNumberGenerator::seed(result_type inSeed) {
    DirectFunctionCall1(setseed, Float8GetDatum(inSeed));
}
PGDLLEXPORT Datum
one_to_many_withPoints(PG_FUNCTION_ARGS) {
    FuncCallContext     *funcctx;
    TupleDesc            tuple_desc;

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


        /**********************************************************************/
        // CREATE OR REPLACE FUNCTION pgr_withPoint(
        // edges_sql TEXT,
        // points_sql TEXT,
        // start_pid BIGINT,
        // end_pids ANYARRAY,
        // directed BOOLEAN -- DEFAULT true,
        // driving_side CHAR -- DEFAULT 'b',
        // details BOOLEAN -- DEFAULT false,
        // only_cost BOOLEAN DEFAULT false,



        process(
                text_to_cstring(PG_GETARG_TEXT_P(0)),
                text_to_cstring(PG_GETARG_TEXT_P(1)),
                PG_GETARG_INT64(2),
                PG_GETARG_ARRAYTYPE_P(3),
                PG_GETARG_BOOL(4),
                text_to_cstring(PG_GETARG_TEXT_P(5)),
                PG_GETARG_BOOL(6),
                PG_GETARG_BOOL(7),
                &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;

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


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

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


        // postgres starts counting from 1
        values[0] = Int32GetDatum(funcctx->call_cntr + 1);
        values[1] = Int32GetDatum(result_tuples[funcctx->call_cntr].seq);
        values[2] = Int64GetDatum(result_tuples[funcctx->call_cntr].end_id);
        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);
    }
}
Exemple #8
0
/* ------------------------------------------------
 * hash_metapage_info()
 *
 * Get the meta-page information for a hash index
 *
 * Usage: SELECT * FROM hash_metapage_info(get_raw_page('con_hash_index', 0))
 * ------------------------------------------------
 */
Datum
hash_metapage_info(PG_FUNCTION_ARGS)
{
	bytea	   *raw_page = PG_GETARG_BYTEA_P(0);
	Page		page;
	HashMetaPageData *metad;
	TupleDesc	tupleDesc;
	HeapTuple	tuple;
	int			i,
				j;
	Datum		values[16];
	bool		nulls[16];
	Datum		spares[HASH_MAX_SPLITPOINTS];
	Datum		mapp[HASH_MAX_BITMAPS];

	if (!superuser())
		ereport(ERROR,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
				 (errmsg("must be superuser to use raw page functions"))));

	page = verify_hash_page(raw_page, LH_META_PAGE);

	/* Build a tuple descriptor for our result type */
	if (get_call_result_type(fcinfo, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
		elog(ERROR, "return type must be a row type");
	tupleDesc = BlessTupleDesc(tupleDesc);

	metad = HashPageGetMeta(page);

	MemSet(nulls, 0, sizeof(nulls));

	j = 0;
	values[j++] = Int64GetDatum((int64) metad->hashm_magic);
	values[j++] = Int64GetDatum((int64) metad->hashm_version);
	values[j++] = Float8GetDatum(metad->hashm_ntuples);
	values[j++] = Int32GetDatum((int32) metad->hashm_ffactor);
	values[j++] = Int32GetDatum((int32) metad->hashm_bsize);
	values[j++] = Int32GetDatum((int32) metad->hashm_bmsize);
	values[j++] = Int32GetDatum((int32) metad->hashm_bmshift);
	values[j++] = Int64GetDatum((int64) metad->hashm_maxbucket);
	values[j++] = Int64GetDatum((int64) metad->hashm_highmask);
	values[j++] = Int64GetDatum((int64) metad->hashm_lowmask);
	values[j++] = Int64GetDatum((int64) metad->hashm_ovflpoint);
	values[j++] = Int64GetDatum((int64) metad->hashm_firstfree);
	values[j++] = Int64GetDatum((int64) metad->hashm_nmaps);
	values[j++] = ObjectIdGetDatum((Oid) metad->hashm_procid);

	for (i = 0; i < HASH_MAX_SPLITPOINTS; i++)
		spares[i] = Int64GetDatum((int64) metad->hashm_spares[i]);
	values[j++] = PointerGetDatum(construct_array(spares,
												  HASH_MAX_SPLITPOINTS,
												  INT8OID,
												  8, FLOAT8PASSBYVAL, 'd'));

	for (i = 0; i < HASH_MAX_BITMAPS; i++)
		mapp[i] = Int64GetDatum((int64) metad->hashm_mapp[i]);
	values[j++] = PointerGetDatum(construct_array(mapp,
												  HASH_MAX_BITMAPS,
												  INT8OID,
												  8, FLOAT8PASSBYVAL, 'd'));

	tuple = heap_form_tuple(tupleDesc, values, nulls);

	PG_RETURN_DATUM(HeapTupleGetDatum(tuple));
}
/*
 * Update the eof and filetupcount of a parquet table.
 */
void
UpdateParquetFileSegInfo(Relation parentrel,
				  AppendOnlyEntry *aoEntry,
				  int segno,
				  int64 eof,
				  int64 eof_uncompressed,
				  int64 tuples_added)
{

	LockAcquireResult acquireResult;

	Relation			pg_parquetseg_rel;
	TupleDesc			pg_parquetseg_dsc;
	ScanKeyData			key[1];
	SysScanDesc			parquetscan;
	HeapTuple			tuple, new_tuple;
	Datum				filetupcount;
	Datum				new_tuple_count;
	Datum			   *new_record;
	bool			   *new_record_nulls;
	bool			   *new_record_repl;
	bool				isNull;

	/* overflow sanity checks. don't check the same for tuples_added,
	 * it may be coming as a negative diff from gp_update_ao_master_stats */
	Assert(eof >= 0);

	Insist(Gp_role != GP_ROLE_EXECUTE);

	elog(DEBUG3, "UpdateParquetFileSegInfo called. segno = %d", segno);

	if (Gp_role != GP_ROLE_DISPATCH)
	{
		/*
		 * Verify we already have the write-lock!
		 */
		acquireResult = LockRelationAppendOnlySegmentFile(
													&parentrel->rd_node,
													segno,
													AccessExclusiveLock,
													/* dontWait */ false);
		if (acquireResult != LOCKACQUIRE_ALREADY_HELD)
		{
			elog(ERROR, "Should already have the (transaction-scope) write-lock on Parquet segment file #%d, "
				 "relation %s", segno, RelationGetRelationName(parentrel));
		}
	}

	/*
	 * Open the aoseg relation and its index.
	 */
	pg_parquetseg_rel = heap_open(aoEntry->segrelid, RowExclusiveLock);
	pg_parquetseg_dsc = pg_parquetseg_rel->rd_att;

	/*
	 * Setup a scan key to fetch from the index by segno.
	 */
	ScanKeyInit(&key[0], (AttrNumber) Anum_pg_parquetseg_segno,
			BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(segno));

	parquetscan = systable_beginscan(pg_parquetseg_rel, aoEntry->segidxid, TRUE,
			SnapshotNow, 1, &key[0]);

	tuple = systable_getnext(parquetscan);

	if (!HeapTupleIsValid(tuple))
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
				errmsg("parquet table \"%s\" file segment \"%d\" entry "
						"does not exist", RelationGetRelationName(parentrel),
						segno)));

	new_record = palloc0(sizeof(Datum) * pg_parquetseg_dsc->natts);
	new_record_nulls = palloc0(sizeof(bool) * pg_parquetseg_dsc->natts);
	new_record_repl = palloc0(sizeof(bool) * pg_parquetseg_dsc->natts);

	/* get the current tuple count so we can add to it */
	filetupcount = fastgetattr(tuple,
								Anum_pg_parquetseg_tupcount,
								pg_parquetseg_dsc,
								&isNull);

	if(isNull)
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
				errmsg("got invalid pg_aoseg filetupcount value: NULL")));

	/* calculate the new tuple count */
	new_tuple_count = DirectFunctionCall2(float8pl,
										  filetupcount,
										  Float8GetDatum((float8)tuples_added));

	/*
	 * Build a tuple to update
	 */
	new_record[Anum_pg_parquetseg_eof - 1] = Float8GetDatum((float8)eof);
	new_record_repl[Anum_pg_parquetseg_eof - 1] = true;

	new_record[Anum_pg_parquetseg_tupcount - 1] = new_tuple_count;
	new_record_repl[Anum_pg_parquetseg_tupcount - 1] = true;

	new_record[Anum_pg_parquetseg_eofuncompressed - 1] = Float8GetDatum((float8)eof_uncompressed);
	new_record_repl[Anum_pg_parquetseg_eofuncompressed - 1] = true;

	/*
	 * update the tuple in the pg_aoseg table
	 */
	new_tuple = heap_modify_tuple(tuple, pg_parquetseg_dsc, new_record,
								new_record_nulls, new_record_repl);

	simple_heap_update(pg_parquetseg_rel, &tuple->t_self, new_tuple);

	CatalogUpdateIndexes(pg_parquetseg_rel, new_tuple);

	heap_freetuple(new_tuple);

	/* Finish up scan */
	systable_endscan(parquetscan);
	heap_close(pg_parquetseg_rel, RowExclusiveLock);

	pfree(new_record);
	pfree(new_record_nulls);
	pfree(new_record_repl);
}
Exemple #10
0
Datum
#else // _MSC_VER
PGDLLEXPORT Datum
#endif // _MSC_VER
kshortest_path(PG_FUNCTION_ARGS)
{
  FuncCallContext     *funcctx;
  int                  call_cntr;
  int                  max_calls;
  TupleDesc            tuple_desc;
  ksp_path_element_t      *path;
  void * toDel;

  /* stuff done only on the first call of the function */
  if (SRF_IS_FIRSTCALL())
    {
      MemoryContext   oldcontext;
      int path_count = 0;
      int ret;

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


      ret = compute_kshortest_path(text2char(PG_GETARG_TEXT_P(0)), /* SQL string */
                                  PG_GETARG_INT32(1),             /* source id */
                                  PG_GETARG_INT32(2),             /* target_id */
                                  PG_GETARG_INT32(3),             /* number of paths */
                                  PG_GETARG_BOOL(4), 		  /* has reverse_cost */
				  &path, 
				  &path_count);
      toDel=path;
#ifdef DEBUG
      if (ret >= 0) 
        {
          int i;
        
          for (i = 0; i < path_count; i++) 
            {
              DBG("Step %i route_id  %d ", i, path[i].route_id);
              DBG("        vertex_id  %d ", path[i].vertex_id);
              DBG("        edge_id    %d ", path[i].edge_id);
              DBG("        cost       %f ", path[i].cost);
            }
        }
#endif
     DBG("Path-Cnt  %i ", path_count);
	
      /* total number of tuples to be returned */
      funcctx->max_calls = path_count;
      funcctx->user_fctx = path;

      funcctx->tuple_desc = 
        BlessTupleDesc(RelationNameGetTupleDesc("pgr_costResult3"));

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

  if (call_cntr < max_calls)    /* do when there is more left to send */
    {
      HeapTuple    tuple;
      Datum        result;
     /* //Datum values[4];
      //bool nulls[4]; */

      Datum *values;
      bool* nulls;

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


      values[0] = Int32GetDatum(call_cntr);
      nulls[0] = false;
      values[1] = Int32GetDatum(path[call_cntr].route_id);
      nulls[1] = false;
      values[2] = Int32GetDatum(path[call_cntr].vertex_id);
      nulls[2] = false;
      values[3] = Int32GetDatum(path[call_cntr].edge_id);
      nulls[3] = false;
      values[4] = Float8GetDatum(path[call_cntr].cost);
      nulls[4] = false;

      tuple = heap_form_tuple(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 */
    {
	free(path);
      SRF_RETURN_DONE(funcctx);
    }
}
Exemple #11
0
static int compute_alpha_shape(char* sql, vertex_t **res, int *res_count)
{

    int SPIcode;
    void *SPIplan;
    Portal SPIportal;
    bool moredata = TRUE;
    int ntuples;
    vertex_t *vertices = NULL;
    int total_tuples = 0;
    vertex_columns_t vertex_columns = {.id= -1, .x= -1, .y= -1};
    char *err_msg;
    int ret = -1;

    DBG("start alpha_shape\n");

    SPIcode = SPI_connect();
    if (SPIcode  != SPI_OK_CONNECT)
    {
        elog(ERROR, "alpha_shape: couldn't open a connection to SPI");
        return -1;
    }

    SPIplan = SPI_prepare(sql, 0, NULL);
    if (SPIplan  == NULL)
    {
        elog(ERROR, "alpha_shape: couldn't create query plan via SPI");
        return -1;
    }

    if ((SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true)) == NULL)
    {
        elog(ERROR, "alpha_shape: SPI_cursor_open('%s') returns NULL", sql);
        return -1;
    }

    while (moredata == TRUE)
    {
        SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);

        if (vertex_columns.id == -1)
        {
            if (fetch_vertices_columns(SPI_tuptable, &vertex_columns) == -1)
                return finish(SPIcode, ret);
        }

        ntuples = SPI_processed;
        total_tuples += ntuples;
        if (!vertices)
            vertices = palloc(total_tuples * sizeof(vertex_t));
        else
            vertices = repalloc(vertices, total_tuples * sizeof(vertex_t));

        if (vertices == NULL)
        {
            elog(ERROR, "Out of memory");
            return finish(SPIcode, ret);
        }

        if (ntuples > 0)
        {
            int t;
            SPITupleTable *tuptable = SPI_tuptable;
            TupleDesc tupdesc = SPI_tuptable->tupdesc;

            for (t = 0; t < ntuples; t++)
            {
                HeapTuple tuple = tuptable->vals[t];
                fetch_vertex(&tuple, &tupdesc, &vertex_columns,
                             &vertices[total_tuples - ntuples + t]);
            }
            SPI_freetuptable(tuptable);
        }
        else
        {
            moredata = FALSE;
        }
    }


    // if (total_tuples < 2) //this was the buggy code of the pgrouting project.
    // TODO: report this as a bug to the pgrouting project
    // the CGAL alpha-shape function crashes if called with less than three points!!!

    if (total_tuples == 0) {
        elog(ERROR, "Distance is too short. no vertex for alpha shape calculation. alpha shape calculation needs at least 3 vertices.");
    }
    if (total_tuples == 1) {
        elog(ERROR, "Distance is too short. only 1 vertex for alpha shape calculation. alpha shape calculation needs at least 3 vertices.");
    }
    if (total_tuples == 2) {
        elog(ERROR, "Distance is too short. only 2 vertices for alpha shape calculation. alpha shape calculation needs at least 3 vertices.");
    }
    if (total_tuples < 3)
    {
        // elog(ERROR, "Distance is too short ....");
        return finish(SPIcode, ret);
    }

    DBG("Calling CGAL alpha-shape\n");

    profstop("extract", prof_extract);
    profstart(prof_alpha);

    ret = alpha_shape(vertices, total_tuples, res, res_count, &err_msg);

    profstop("alpha", prof_alpha);
    profstart(prof_store);

    if (ret < 0)
    {
        //elog(ERROR, "Error computing shape: %s", err_msg);
        ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED), errmsg("Error computing shape: %s", err_msg)));
    }

    return finish(SPIcode, ret);
}

PG_FUNCTION_INFO_V1(alphashape);

Datum alphashape(PG_FUNCTION_ARGS)
{
    FuncCallContext      *funcctx;
    int                  call_cntr;
    int                  max_calls;
    TupleDesc            tuple_desc;
    vertex_t     *res = 0;

    /* stuff done only on the first call of the function */
    if (SRF_IS_FIRSTCALL())
    {
        MemoryContext   oldcontext;
        int res_count;
        int ret;

        // XXX profiling messages are not thread safe
        profstart(prof_total);
        profstart(prof_extract);

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

        ret = compute_alpha_shape(text2char(PG_GETARG_TEXT_P(0)),
                                  &res, &res_count);

        /* total number of tuples to be returned */
        DBG("Conting tuples number\n");
        funcctx->max_calls = res_count;
        funcctx->user_fctx = res;

        DBG("Total count %i", res_count);

        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 = BlessTupleDesc(tuple_desc);

        MemoryContextSwitchTo(oldcontext);
    }

    /* stuff done on every call of the function */
    DBG("Strange stuff doing\n");
    funcctx = SRF_PERCALL_SETUP();

    call_cntr = funcctx->call_cntr;
    max_calls = funcctx->max_calls;
    tuple_desc = funcctx->tuple_desc;
    res = (vertex_t*) funcctx->user_fctx;

    DBG("Trying to allocate some memory\n");

    if (call_cntr < max_calls)    /* do when there is more left to send */
    {
        HeapTuple    tuple;
        Datum        result;
        Datum *values;
        char* nulls;

        /* This will work for some compilers. If it crashes with segfault, try to change the following block with this one

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

        values[0] = call_cntr;
        nulls[0] = ' ';
        values[1] = Float8GetDatum(res[call_cntr].x);
        nulls[1] = ' ';
        values[2] = Float8GetDatum(res[call_cntr].y);
        nulls[2] = ' ';
        */

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

        values[0] = Float8GetDatum(res[call_cntr].x);
        nulls[0] = ' ';
        values[1] = Float8GetDatum(res[call_cntr].y);
        nulls[1] = ' ';

        DBG("Heap making\n");

        tuple = heap_formtuple(tuple_desc, values, nulls);

        DBG("Datum making\n");

        /* make the tuple into a datum */
        result = HeapTupleGetDatum(tuple);

        DBG("Trying to free some memory\n");

        /* 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 (res) free(res);
        profstop("store", prof_store);
        profstop("total", prof_total);
#ifdef PROFILE
        elog(NOTICE, "_________");
#endif
        SRF_RETURN_DONE(funcctx);
    }
}
Exemple #12
0
static int compute_shortest_path(char* sql, int start_vertex, 
                                 int end_vertex, bool directed, 
                                 bool has_reverse_cost, 
                                 path_element_t **path, int *path_count) 
{

  int SPIcode;
  void *SPIplan;
  Portal SPIportal;
  bool moredata = TRUE;
  int ntuples;
  edge_t *edges = NULL;
  int total_tuples = 0;
  edge_columns_t edge_columns = {id: -1, source: -1, target: -1, 
                                 cost: -1, reverse_cost: -1};
  int v_max_id=0;
  int v_min_id=INT_MAX;

  int s_count = 0;
  int t_count = 0;

  char *err_msg;
  int ret = -1;
  register int z;

  DBG("start shortest_path\n");
        
  SPIcode = SPI_connect();
  if (SPIcode  != SPI_OK_CONNECT)
    {
      elog(ERROR, "shortest_path: couldn't open a connection to SPI");
      return -1;
    }

  SPIplan = SPI_prepare(sql, 0, NULL);
  if (SPIplan  == NULL)
    {
      elog(ERROR, "shortest_path: couldn't create query plan via SPI");
      return -1;
    }

  if ((SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true)) == NULL) 
    {
      elog(ERROR, "shortest_path: SPI_cursor_open('%s') returns NULL", sql);
      return -1;
    }

  while (moredata == TRUE)
    {
      SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);

      if (edge_columns.id == -1) 
        {
          if (fetch_edge_columns(SPI_tuptable, &edge_columns, 
                                 has_reverse_cost) == -1)
	    return finish(SPIcode, ret);
        }

      ntuples = SPI_processed;
      total_tuples += ntuples;
      if (!edges)
        edges = palloc(total_tuples * sizeof(edge_t));
      else
        edges = repalloc(edges, total_tuples * sizeof(edge_t));

      if (edges == NULL) 
        {
          elog(ERROR, "Out of memory");
	    return finish(SPIcode, ret);	  
        }

      if (ntuples > 0) 
        {
          int t;
          SPITupleTable *tuptable = SPI_tuptable;
          TupleDesc tupdesc = SPI_tuptable->tupdesc;
                
          for (t = 0; t < ntuples; t++) 
            {
              HeapTuple tuple = tuptable->vals[t];
              fetch_edge(&tuple, &tupdesc, &edge_columns, 
                         &edges[total_tuples - ntuples + t]);
            }
          SPI_freetuptable(tuptable);
        } 
      else 
        {
          moredata = FALSE;
        }
    }

  //defining min and max vertex id
      
  DBG("Total %i tuples", total_tuples);
    
  for(z=0; z<total_tuples; z++)
  {
    if(edges[z].source<v_min_id)
    v_min_id=edges[z].source;
  
    if(edges[z].source>v_max_id)
      v_max_id=edges[z].source;
		            
    if(edges[z].target<v_min_id)
      v_min_id=edges[z].target;

    if(edges[z].target>v_max_id)
      v_max_id=edges[z].target;      
								        
    DBG("%i <-> %i", v_min_id, v_max_id);
							
  }

  //::::::::::::::::::::::::::::::::::::  
  //:: reducing vertex id (renumbering)
  //::::::::::::::::::::::::::::::::::::
  for(z=0; z<total_tuples; z++)
  {
    //check if edges[] contains source and target
    if(edges[z].source == start_vertex || edges[z].target == start_vertex)
      ++s_count;
    if(edges[z].source == end_vertex || edges[z].target == end_vertex)
      ++t_count;

    edges[z].source-=v_min_id;
    edges[z].target-=v_min_id;
    DBG("%i - %i", edges[z].source, edges[z].target);      
  }

  DBG("Total %i tuples", total_tuples);

  if(s_count == 0)
  {
    elog(ERROR, "Source vertex: %d was not found as vertex of any of the input edges.", start_vertex);
    return -1;
  }
      
  if(t_count == 0)
  {
    elog(ERROR, "Target vertex: %d was not found as vertex of any of the input edges.", end_vertex);
    return -1;
  }
  
  DBG("Calling boost_dijkstra\n");
        
  start_vertex -= v_min_id;
  end_vertex   -= v_min_id;

  ret = boost_dijkstra(edges, total_tuples, start_vertex, end_vertex,
                       directed, has_reverse_cost,
                       path, path_count, &err_msg);

  DBG("SIZE %i\n",*path_count);

  //::::::::::::::::::::::::::::::::
  //:: restoring original vertex id
  //::::::::::::::::::::::::::::::::
  for(z=0;z<*path_count;z++)
  {
    //DBG("vetex %i\n",(*path)[z].vertex_id);
    (*path)[z].vertex_id+=v_min_id;
  }

  DBG("ret = %i\n", ret);

  DBG("*path_count = %i\n", *path_count);

  DBG("ret = %i\n", ret);
  
  if (ret < 0)
    {
      //elog(ERROR, "Error computing path: %s", err_msg);
      ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED), 
        errmsg("Error computing path: %s", err_msg)));
    } 

  if (edges) {
    /* clean up input egdes */
    pfree (edges);
  }
    
  return finish(SPIcode, ret);
}


PG_FUNCTION_INFO_V1(shortest_path);
Datum
shortest_path(PG_FUNCTION_ARGS)
{
  FuncCallContext     *funcctx;
  int                  call_cntr;
  int                  max_calls;
  TupleDesc            tuple_desc;
  path_element_t      *path = NULL;
  char                *sql = NULL;

  /* stuff done only on the first call of the function */
  if (SRF_IS_FIRSTCALL())
    {
      MemoryContext   oldcontext;
      int path_count = 0;
      int ret;

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

      /* edge sql query */
      sql = text2char(PG_GETARG_TEXT_P(0));

      ret = compute_shortest_path(sql,
                                  PG_GETARG_INT32(1),
                                  PG_GETARG_INT32(2),
                                  PG_GETARG_BOOL(3),
                                  PG_GETARG_BOOL(4), &path, &path_count);

      /* clean up sql query string */
      if (sql) {
        pfree (sql);
      }

#ifdef DEBUG
      DBG("Ret is %i", ret);
      if (ret >= 0) 
        {
          int i;
          for (i = 0; i < path_count; i++) 
            {
              DBG("Step %i vertex_id  %i ", i, path[i].vertex_id);
              DBG("        edge_id    %i ", path[i].edge_id);
              DBG("        cost       %f ", path[i].cost);
            }
        }
#endif

      /* total number of tuples to be returned */
      funcctx->max_calls = path_count;
      funcctx->user_fctx = path;

      funcctx->tuple_desc = 
        BlessTupleDesc(RelationNameGetTupleDesc("path_result"));

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

  if (call_cntr < max_calls)    /* do when there is more left to send */
    {
      HeapTuple    tuple;
      Datum        result;
      Datum *values;
      char* nulls;

      /* This will work for some compilers. If it crashes with segfault, try to change the following block with this one    
 
      values = palloc(4 * sizeof(Datum));
      nulls = palloc(4 * sizeof(char));
  
      values[0] = call_cntr;
      nulls[0] = ' ';
      values[1] = Int32GetDatum(path[call_cntr].vertex_id);
      nulls[1] = ' ';
      values[2] = Int32GetDatum(path[call_cntr].edge_id);
      nulls[2] = ' ';
      values[3] = Float8GetDatum(path[call_cntr].cost);
      nulls[3] = ' ';
      */
    
      values = palloc(3 * sizeof(Datum));
      nulls = palloc(3 * sizeof(char));

      values[0] = Int32GetDatum(path[call_cntr].vertex_id);
      nulls[0] = ' ';
      values[1] = Int32GetDatum(path[call_cntr].edge_id);
      nulls[1] = ' ';
      values[2] = Float8GetDatum(path[call_cntr].cost);
      nulls[2] = ' ';
		      
      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 (path) {
        /* clean up returned edge paths
           must be a free because it's malloc'd */
        free (path);
        path = NULL;
      }

      SRF_RETURN_DONE(funcctx);
    }
}
Exemple #13
0
Datum
shortest_path(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);


      compute_shortest_path(pgr_text2char(PG_GETARG_TEXT_P(0)),
                                  PG_GETARG_INT64(1),
                                  PG_GETARG_INT64(2),
                                  PG_GETARG_BOOL(3),
                                  PG_GETARG_BOOL(4), &ret_path, &path_count);

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

      values[0] = Int32GetDatum(ret_path[call_cntr].seq);
      nulls[0] = ' ';
      values[1] = Int32GetDatum(ret_path[call_cntr].seq);
      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);
  }
}
Exemple #14
0
    Datum
turn_restrict_shortest_path_edge(PG_FUNCTION_ARGS)
{

    FuncCallContext     *funcctx;
    uint32_t                  call_cntr;
    uint32_t                  max_calls;
    TupleDesc            tuple_desc;
    path_element_t      *path;
    char *               sql;

    // stuff done only on the first call of the function 
    if (SRF_IS_FIRSTCALL()) {
        MemoryContext   oldcontext;
        size_t path_count = 0;
#ifdef DEBUG
        int ret = -1;
#endif
        int i;
        double s_pos;
        double e_pos;

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

        // verify that the first 5 args are not NULL
        for (i=0; i<7; i++) {
            if(i==2 || i==4) continue;
            if(PG_ARGISNULL(i)) {
                elog(ERROR, "turn_restrict_shortest_path(): Argument %i may not be NULL", i+1);
            }
        }

        if (PG_ARGISNULL(2))
            s_pos = 0.5;
        else {
            s_pos = PG_GETARG_FLOAT8(2);
            if (s_pos < 0.0) s_pos = 0.5;
            if (s_pos > 1.0) s_pos = 0.5;
        }

        if (PG_ARGISNULL(4))
            e_pos = 0.5;
        else {
            e_pos = PG_GETARG_FLOAT8(4);
            if (e_pos < 0.0) e_pos = 0.5;
            if (e_pos > 1.0) e_pos = 0.5;
        }

        if (PG_ARGISNULL(7))
            sql = NULL;
        else {
            sql = pgr_text2char(PG_GETARG_TEXT_P(7));
            if (strlen(sql) == 0)
                sql = NULL;
        }

        PGR_DBG("Calling compute_trsp");

#ifdef DEBUG
        ret =
#endif
            compute_trsp(pgr_text2char(PG_GETARG_TEXT_P(0)),
                    0,  //sdo edge
                    PG_GETARG_INT32(1),
                    s_pos,
                    PG_GETARG_INT32(3),
                    e_pos,
                    PG_GETARG_BOOL(5),
                    PG_GETARG_BOOL(6), 
                    sql,
                    &path, &path_count);
#ifdef DEBUG
        double total_cost = 0;
        PGR_DBG("Ret is %i", ret);
        if (ret >= 0) 
        {
            int i;
            for (i = 0; i < path_count; i++) 
            {
                //     PGR_DBG("Step %i vertex_id  %i ", i, path[i].vertex_id);
                //   PGR_DBG("        edge_id    %i ", path[i].edge_id);
                // PGR_DBG("        cost       %f ", path[i].cost);
                total_cost+=path[i].cost;
            }
        }
        PGR_DBG("Total cost is: %f",total_cost);
#endif

        // total number of tuples to be returned 
        funcctx->max_calls = (uint32_t)path_count;
        funcctx->user_fctx = path;

        funcctx->tuple_desc = 
            BlessTupleDesc(RelationNameGetTupleDesc("pgr_costResult"));

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

    if (call_cntr < max_calls)    // do when there is more left to send 
    {
        HeapTuple    tuple;
        Datum        result;
        Datum *values;
        bool* nulls;

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

        values[0] = Int32GetDatum(call_cntr);
        nulls[0] = false;
        values[1] = Int32GetDatum(path[call_cntr].vertex_id);
        nulls[1] = false;
        values[2] = Int32GetDatum(path[call_cntr].edge_id);
        nulls[2] = false;
        values[3] = Float8GetDatum(path[call_cntr].cost);
        nulls[3] = false;

        tuple = heap_form_tuple(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 
    {
        PGR_DBG("Going to free path");
        if (path) free(path);
        SRF_RETURN_DONE(funcctx);
    }
}
Exemple #15
0
Datum ta_f( PG_FUNCTION_ARGS)
{

	// Declare for TA
	TA_RetCode retCode;
	TA_Real *closePrice = NULL;
	TA_Real *out;

	TA_Integer outBeg;
	TA_Integer outNbElement;

	// Declare for postgres
	FuncCallContext *funcctx;
	int call_cntr;
	int max_calls;
	Datum *result = NULL;
	int dim;
	int z;
	ArrayType *ur = PG_GETARG_ARRAYTYPE_P(0);

	if (array_contains_nulls(ur))
	{
		ereport(ERROR,
				( errcode(ERRCODE_ARRAY_ELEMENT_ERROR), errmsg("cannot work with arrays containing NULLs") ));
	}

	dim = ARRNELEMS(ur);
	closePrice = ARRPTR(ur);

	if (SRF_IS_FIRSTCALL())
	{
		MemoryContext oldcontext;

		funcctx = SRF_FIRSTCALL_INIT();
		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
		/* One-time setup code appears here: */
		retCode = TA_Initialize();
		if (retCode != TA_SUCCESS)
		{
			ereport(ERROR,
					( errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Cannot initialize TA-Lib (%d)!\n", retCode) ));
		}

		out = palloc(dim * sizeof(TA_Real));

		retCode = TA_MA(0, dim - 1, &closePrice[0], 5, TA_MAType_SMA, &outBeg,
				&outNbElement, &out[0]);

		result = palloc(outNbElement * sizeof(Datum));

		// Error log for debugging
		/*
		ereport(NOTICE,
				(errmsg("dims %d,  outBeg: %d, outNbElement %d\n", dim, outBeg, outNbElement)));
		*/
		for (z = 0; z < dim; z++)
		{
			// Error log for debugging
			//ereport(NOTICE, (errmsg("z: %d, out[z]: %5.1f", z, out[z])));
			if(z > outBeg-1) {
				result[z] = Float8GetDatum(out[z-outBeg]);
				continue;
			}
			result[z] = NULL;
		}
		TA_Shutdown();

		funcctx->max_calls = dim;
		funcctx->user_fctx = result;
		MemoryContextSwitchTo(oldcontext);
	}

	/* stuff done on every call of the function */
	funcctx = SRF_PERCALL_SETUP();

	call_cntr = funcctx->call_cntr;
	max_calls = funcctx->max_calls;

	if (call_cntr < max_calls)
	{
		if(((Datum *) funcctx->user_fctx)[call_cntr]) {
			SRF_RETURN_NEXT(funcctx, ((Datum *) funcctx->user_fctx)[call_cntr]);
		}
		SRF_RETURN_NEXT_NULL(funcctx);
	}
	SRF_RETURN_DONE(funcctx);
}
Exemple #16
0
PGDLLEXPORT Datum
newTSP(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                          */
        /*

           CREATE OR REPLACE FUNCTION pgr_newTSP(
           matrix_row_sql TEXT,
           start_id BIGINT DEFAULT 0,
           end_id BIGINT DEFAULT 0,

           max_processing_time FLOAT DEFAULT '+infinity'::FLOAT,

           tries_per_temperature INTEGER DEFAULT 500,
           max_changes_per_temperature INTEGER DEFAULT 60,
           max_consecutive_non_changes INTEGER DEFAULT 200,

           initial_temperature FLOAT DEFAULT 100,
           final_temperature FLOAT DEFAULT 0.1,
           cooling_factor FLOAT DEFAULT 0.9,

           randomize BOOLEAN DEFAULT true,
           */

        process(
                text_to_cstring(PG_GETARG_TEXT_P(0)),
                PG_GETARG_INT64(1),
                PG_GETARG_INT64(2),

                PG_GETARG_FLOAT8(3),

                PG_GETARG_INT32(4),
                PG_GETARG_INT32(5),
                PG_GETARG_INT32(6),

                PG_GETARG_FLOAT8(7),
                PG_GETARG_FLOAT8(8),
                PG_GETARG_FLOAT8(9),

                PG_GETARG_BOOL(10),
                &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                          */
        // OUT seq INTEGER,
        // OUT node BIGINT,
        // OUT cost FLOAT,
        // OUT agg_cost FLOAT

        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(funcctx->call_cntr + 1);
        values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr].node);
        values[2] = Float8GetDatum(result_tuples[funcctx->call_cntr].cost);
        values[3] = 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);
    }
}
Exemple #17
0
static int compute_shortest_path_astar(char* sql, int source_vertex_id, 
                       int target_vertex_id, bool directed, 
                       bool has_reverse_cost, 
                       path_element_t **path, int *path_count) 
{

  int SPIcode;
  void *SPIplan;
  Portal SPIportal;
  bool moredata = TRUE;
  int ntuples;
  edge_astar_t *edges = NULL;
  int total_tuples = 0;

  int v_max_id=0;
  int v_min_id=INT_MAX;  

  edge_astar_columns_t edge_columns = {.id= -1, .source= -1, .target= -1, 
                       .cost= -1, .reverse_cost= -1, 
                       .s_x= -1, .s_y= -1, .t_x= -1, .t_y= -1};
  char *err_msg;
  int ret = -1;
  register int z;

  int s_count=0;
  int t_count=0;

  struct vItem
  {
    int id;
    int key;
  };

  DBG("start shortest_path_astar\n");

  SPIcode = SPI_connect();
  if (SPIcode  != SPI_OK_CONNECT) {
      elog(ERROR, "shortest_path_astar: couldn't open a connection to SPI");
      return -1;
  }

  SPIplan = SPI_prepare(sql, 0, NULL);
  if (SPIplan  == NULL) {
      elog(ERROR, "shortest_path_astar: couldn't create query plan via SPI");
      return -1;
  }

  if ((SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true)) == NULL) {
      elog(ERROR, "shortest_path_astar: SPI_cursor_open('%s') returns NULL", 
       sql);
      return -1;
  }

  while (moredata == TRUE) {
      SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);

      if (edge_columns.id == -1) {
          if (fetch_edge_astar_columns(SPI_tuptable, &edge_columns, 
                           has_reverse_cost) == -1)
              return finish(SPIcode, ret);
      }

      ntuples = SPI_processed;
      total_tuples += ntuples;
      if (!edges)
          edges = palloc(total_tuples * sizeof(edge_astar_t));
      else
          edges = repalloc(edges, total_tuples * sizeof(edge_astar_t));

      if (edges == NULL) {
          elog(ERROR, "Out of memory");
          return finish(SPIcode, ret);
      }

      if (ntuples > 0) {
          int t;
          SPITupleTable *tuptable = SPI_tuptable;
          TupleDesc tupdesc = SPI_tuptable->tupdesc;

          for (t = 0; t < ntuples; t++) {
            HeapTuple tuple = tuptable->vals[t];
            fetch_edge_astar(&tuple, &tupdesc, &edge_columns, 
                   &edges[total_tuples - ntuples + t]);
          }
          SPI_freetuptable(tuptable);
      } 
      else {
          moredata = FALSE;
      }
  }

  //defining min and max vertex id

  DBG("Total %i tuples", total_tuples);

  for(z=0; z<total_tuples; z++) {
    if(edges[z].source<v_min_id) v_min_id=edges[z].source;
    if(edges[z].source>v_max_id) v_max_id=edges[z].source;
    if(edges[z].target<v_min_id) v_min_id=edges[z].target;
    if(edges[z].target>v_max_id) v_max_id=edges[z].target;      

    DBG("%i <-> %i", v_min_id, v_max_id);
  }

  //::::::::::::::::::::::::::::::::::::  
  //:: reducing vertex id (renumbering)
  //::::::::::::::::::::::::::::::::::::
  for(z=0; z<total_tuples; z++) {
    //check if edges[] contains source and target
    if(edges[z].source == source_vertex_id || 
       edges[z].target == source_vertex_id)
      ++s_count;
    if(edges[z].source == target_vertex_id || 
       edges[z].target == target_vertex_id)
      ++t_count;

    edges[z].source-=v_min_id;
    edges[z].target-=v_min_id;
    DBG("%i - %i", edges[z].source, edges[z].target);
  }

  DBG("Total %i tuples", total_tuples);

  if(s_count == 0) {
    elog(ERROR, "Start vertex was not found.");
    return -1;
  }

  if(t_count == 0) {
    elog(ERROR, "Target vertex was not found.");
    return -1;
  }

  DBG("Total %i tuples", total_tuples);

  profstop("extract", prof_extract);
  profstart(prof_astar);

  DBG("Calling boost_astar <%i>\n", total_tuples);

  // calling C++ A* function    
  ret = boost_astar(edges, total_tuples, source_vertex_id-v_min_id, 
            target_vertex_id-v_min_id,
            directed, has_reverse_cost,
            path, path_count, &err_msg);

  if (ret < 0) {
      elog(ERROR, "Error computing path: %s", err_msg);
  } 

  DBG("SIZE %i\n",*path_count);
  DBG("ret =  %i\n",ret);

  //::::::::::::::::::::::::::::::::
  //:: restoring original vertex id
  //::::::::::::::::::::::::::::::::
  for(z=0; z<*path_count; z++) {
    //DBG("vetex %i\n",(*path)[z].vertex_id);
    (*path)[z].vertex_id += v_min_id;
  }  

  profstop("astar", prof_astar);
  profstart(prof_store);

  return finish(SPIcode, ret);
}


PG_FUNCTION_INFO_V1(shortest_path_astar);
Datum
shortest_path_astar(PG_FUNCTION_ARGS)
{
  FuncCallContext     *funcctx;
  int                  call_cntr;
  int                  max_calls;
  TupleDesc            tuple_desc;
  path_element_t      *path = 0;

  /* stuff done only on the first call of the function */
  if (SRF_IS_FIRSTCALL()) {
      MemoryContext   oldcontext;
      int path_count = 0;
      int ret;

      // XXX profiling messages are not thread safe
      profstart(prof_total);
      profstart(prof_extract);

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


      ret = compute_shortest_path_astar(text2char(PG_GETARG_TEXT_P(0)),
                    PG_GETARG_INT32(1),
                    PG_GETARG_INT32(2),
                    PG_GETARG_BOOL(3),
                    PG_GETARG_BOOL(4), 
                    &path, &path_count);

#ifdef DEBUG
      DBG("Ret is %i", ret);
      int i;
      for (i = 0; i < path_count; i++) {
          DBG("Step # %i vertex_id  %i ", i, path[i].vertex_id);
          DBG("        edge_id    %i ", path[i].edge_id);
          DBG("        cost       %f ", path[i].cost);
      }
#endif

      /* total number of tuples to be returned */
      DBG("Conting tuples number\n");
      funcctx->max_calls = path_count;
      funcctx->user_fctx = path;

      DBG("Path count %i", path_count);

      funcctx->tuple_desc = 
            BlessTupleDesc(RelationNameGetTupleDesc("pgr_costResult"));

      MemoryContextSwitchTo(oldcontext);
  }

  /* stuff done on every call of the function */
  DBG("Strange stuff doing\n");

  funcctx = SRF_PERCALL_SETUP();

  call_cntr = funcctx->call_cntr;
  max_calls = funcctx->max_calls;
  tuple_desc = funcctx->tuple_desc;
  path = (path_element_t*) funcctx->user_fctx;

  DBG("Trying to allocate some memory\n");

  if (call_cntr < max_calls) {   /* do when there is more left to send */
        HeapTuple    tuple;
        Datum        result;
        Datum *values;
        char* nulls;

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

        values[0] = Int32GetDatum(call_cntr);
        nulls[0] = ' ';
        values[1] = Int32GetDatum(path[call_cntr].vertex_id);
        nulls[1] = ' ';
        values[2] = Int32GetDatum(path[call_cntr].edge_id);
        nulls[2] = ' ';
        values[3] = Float8GetDatum(path[call_cntr].cost);
        nulls[3] = ' ';

        DBG("Heap making\n");

        tuple = heap_formtuple(tuple_desc, values, nulls);

        DBG("Datum making\n");

        /* make the tuple into a datum */
        result = HeapTupleGetDatum(tuple);

        DBG("Trying to free some memory\n");

        /* 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 (path) free(path);
        profstop("store", prof_store);
        profstop("total", prof_total);
#ifdef PROFILE
        elog(NOTICE, "_________");
#endif
        SRF_RETURN_DONE(funcctx);
    }
}
Exemple #18
0
/* Clause 3.3.1.3 */
Datum MarketWatchFrame1(PG_FUNCTION_ARGS)
{
	int i;

	int status = 0;
	double old_mkt_cap = 0.0;
	double new_mkt_cap = 0.0;
	double pct_change = 0.0;

	struct pg_tm tt, *tm = &tt;
	int64 acct_id = PG_GETARG_INT64(0);
	int64 cust_id = PG_GETARG_INT64(1);
	int64 ending_co_id = PG_GETARG_INT64(2);
	char *industry_name_p = (char *) PG_GETARG_TEXT_P(3);
	DateADT start_date_p = PG_GETARG_DATEADT(4);
	int64 starting_co_id = PG_GETARG_INT64(5);

	int ret;
	TupleDesc tupdesc;
	SPITupleTable *tuptable = NULL;
	HeapTuple tuple = NULL;

	Datum result;

	char buf[MAXDATELEN + 1];
	char industry_name[IN_NAME_LEN + 1];

	char sql[2048] = "";

	j2date(start_date_p + POSTGRES_EPOCH_JDATE,
	   &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
	EncodeDateOnly(tm, DateStyle, buf);

	strcpy(industry_name, DatumGetCString(DirectFunctionCall1(textout,
			PointerGetDatum(industry_name_p))));

#ifdef DEBUG
	dump_mwf1_inputs(acct_id, cust_id, ending_co_id, industry_name,
			buf, starting_co_id);
#endif

	SPI_connect();

	if (cust_id != 0) {
		sprintf(sql, MWF1_1, cust_id);
	} else if (industry_name[0] != '\0') {
		sprintf(sql, MWF1_2, industry_name, starting_co_id, ending_co_id);
	} else if (acct_id != 0) {
		sprintf(sql, MWF1_3, acct_id);
	} else {
		status = BAD_INPUT_DATA;
	}
#ifdef DEBUG
	elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
	ret = SPI_exec(sql, 0);
	if (ret != SPI_OK_SELECT) {
		dump_mwf1_inputs(acct_id, cust_id, ending_co_id, industry_name,
				buf, starting_co_id);
		FAIL_FRAME(sql);
	}

	if (status != BAD_INPUT_DATA) {
		int count = SPI_processed;

		TupleDesc tupdesc4;
		SPITupleTable *tuptable4 = NULL;
		HeapTuple tuple4 = NULL;

		char *symbol;
		char *new_price;
		char *old_price;
		char *s_num_out;

		tupdesc = SPI_tuptable->tupdesc;
		tuptable = SPI_tuptable;
		for (i = 0; i < count; i++) {
			tuple = tuptable->vals[i];
			symbol = SPI_getvalue(tuple, tupdesc, 1);
#ifdef DEBUG
			elog(NOTICE, "  symbol = '%s'", symbol);
#endif /* DEBUG */

			sprintf(sql, MWF1_4, symbol);
#ifdef DEBUG
			elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
			ret = SPI_exec(sql, 0);
			if (ret != SPI_OK_SELECT || SPI_processed == 0) {
				dump_mwf1_inputs(acct_id, cust_id, ending_co_id,
						industry_name, buf, starting_co_id);
				FAIL_FRAME(sql);
				continue;
			}
			tupdesc4 = SPI_tuptable->tupdesc;
			tuptable4 = SPI_tuptable;
			tuple4 = tuptable4->vals[0];
			new_price = SPI_getvalue(tuple4, tupdesc4, 1);
#ifdef DEBUG
			elog(NOTICE, "  new_price  = %s", new_price);
			elog(NOTICE, "  new_price  = %f", atof(new_price));
#endif /* DEBUG */

			sprintf(sql, MWF1_5, symbol);
#ifdef DEBUG
			elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
			ret = SPI_exec(sql, 0);
			if (ret != SPI_OK_SELECT) {
				dump_mwf1_inputs(acct_id, cust_id, ending_co_id,
						industry_name, buf, starting_co_id);
				elog(NOTICE, "ERROR: sql not ok = %d", ret);
			}
			tupdesc4 = SPI_tuptable->tupdesc;
			tuptable4 = SPI_tuptable;
			tuple4 = tuptable4->vals[0];
			s_num_out = SPI_getvalue(tuple4, tupdesc4, 1);
#ifdef DEBUG
			elog(NOTICE, "  s_num_out  = %s", s_num_out);
#endif /* DEBUG */

			sprintf(sql, MWF1_6, symbol, pstrdup(buf));
#ifdef DEBUG
			elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
			ret = SPI_exec(sql, 0);
			if (ret != SPI_OK_SELECT) {
				dump_mwf1_inputs(acct_id, cust_id, ending_co_id,
						industry_name, buf, starting_co_id);
				FAIL_FRAME(sql);
			}

			if (SPI_processed == 0) {
				elog(NOTICE, "No rows returned for getting old_price.");
			} else {
				tupdesc4 = SPI_tuptable->tupdesc;
				tuptable4 = SPI_tuptable;
				tuple4 = tuptable4->vals[0];
				old_price = SPI_getvalue(tuple4, tupdesc4, 1);
#ifdef DEBUG
				elog(NOTICE, "  old_price  = %s", old_price);
				elog(NOTICE, "  old_price  = %f", atof(old_price));
#endif /* DEBUG */
				old_mkt_cap += atof(s_num_out) * atof(old_price);
			}
			new_mkt_cap += atof(s_num_out) * atof(new_price);

#ifdef DEBUG
			elog(NOTICE, "old_mkt_cap = %f", old_mkt_cap);
			elog(NOTICE, "new_mkt_cap = %f", new_mkt_cap);
#endif /* DEBUG */
		}
		pct_change = 100.0 * (new_mkt_cap / old_mkt_cap - 1.0);
#ifdef DEBUG
		elog(NOTICE, "pct_change = %f", pct_change);
#endif /* DEBUG */
	}

#ifdef DEBUG                                                                    
	elog(NOTICE, "MWF1 OUT: 1 %f", pct_change);
#endif /* DEBUG */

	SPI_finish();
	result = DirectFunctionCall1(float8_numeric, Float8GetDatum(pct_change));
	PG_RETURN_NUMERIC(result);
}
Exemple #19
0
Datum 
formatter_import(PG_FUNCTION_ARGS)
{
	HeapTuple			tuple;
	TupleDesc           tupdesc;
	MemoryContext 		m, oldcontext;
	format_t           *myData;
	char               *data_buf;
	int                 ncolumns = 0;
	int			  		data_cur;
	int                 data_len;
	int                 i;
	
	/* Must be called via the external table format manager */
	if (!CALLED_AS_FORMATTER(fcinfo))
		elog(ERROR, "formatter_import: not called by format manager");
	
	tupdesc = FORMATTER_GET_TUPDESC(fcinfo);
	
	/* Get our internal description of the formatter */
	ncolumns = tupdesc->natts;
	myData = (format_t *) FORMATTER_GET_USER_CTX(fcinfo);
	
	if (myData == NULL)
	{

		myData          = palloc(sizeof(format_t));
		myData->ncols   = ncolumns;
		myData->values  = palloc(sizeof(Datum) * ncolumns);
		myData->nulls   = palloc(sizeof(bool) * ncolumns);
		
		/* misc verification */
		for (i = 0; i < ncolumns; i++)
		{
			Oid   type   = tupdesc->attrs[i]->atttypid;
			//int32 typmod = tupdesc->attrs[i]->atttypmod;

			/* Don't know how to format dropped columns, error for now */
			if (tupdesc->attrs[i]->attisdropped)
				elog(ERROR, "formatter_import: dropped columns");

			switch (type)
			{
				case FLOAT8OID:
				case VARCHAROID:
				case BPCHAROID:
				case TEXTOID:
					break;
					
				default:
				{
					elog(ERROR, "formatter_import error: unsupported data type");
					break;
				}
			}
		}

		FORMATTER_SET_USER_CTX(fcinfo, myData);

	}
	if (myData->ncols != ncolumns)
		elog(ERROR, "formatter_import: unexpected change of output record type");

	/* get our input data buf and number of valid bytes in it */
	data_buf = FORMATTER_GET_DATABUF(fcinfo);
	data_len = FORMATTER_GET_DATALEN(fcinfo); 
	data_cur = FORMATTER_GET_DATACURSOR(fcinfo);
	
	/* start clean */
	MemSet(myData->values, 0, ncolumns * sizeof(Datum));
	MemSet(myData->nulls, true, ncolumns * sizeof(bool));
	
	/* =======================================================================
	 *                            MAIN FORMATTING CODE
	 *
	 * Currently this code assumes:
	 *  - Homogoneos hardware => No need to convert data to network byte order
	 *  - Support for TEXT/VARCHAR/BPCHAR/FLOAT8 only
	 *  - Length Prefixed strings
	 *  - No end of record tags, checksums, or optimizations for alignment.
	 *  - NULL values are cast to some sensible default value (NaN, "")
	 *
	 * ======================================================================= */
	m = FORMATTER_GET_PER_ROW_MEM_CTX(fcinfo);
	oldcontext = MemoryContextSwitchTo(m);

	for (i = 0; i < ncolumns; i++)
	{
		Oid		type    	= tupdesc->attrs[i]->atttypid;
		//int	typmod		= tupdesc->attrs[i]->atttypmod;
		int		remaining	= 0;
		int		attr_len 	= 0;
		
		remaining = data_len - data_cur;
		
		switch (type)
		{
			case FLOAT8OID:
			{
				float8 value;

				attr_len = sizeof(value);
				
				if (remaining < attr_len)
				{
					MemoryContextSwitchTo(oldcontext);
					FORMATTER_RETURN_NOTIFICATION(fcinfo, FMT_NEED_MORE_DATA);
				}
				
				memcpy(&value, data_buf + data_cur, attr_len);
				
				if(value != NULL_FLOAT8_VALUE)
				{
					myData->nulls[i] = false;
					myData->values[i] = Float8GetDatum(value);
				}
				
				/* TODO: check for nan? */
				
				break;
			}

			case TEXTOID:
			case VARCHAROID:
			case BPCHAROID:
			{
				text*	value;
				int32	len;
				bool	nextlen = remaining >= sizeof(len);
				
				if (nextlen)
					memcpy(&len, data_buf + data_cur, sizeof(len));

				/* if len or data bytes don't exist in this buffer, return */
				if (!nextlen || (nextlen && (remaining - sizeof(len) < len)))
				{
					MemoryContextSwitchTo(oldcontext);
					FORMATTER_RETURN_NOTIFICATION(fcinfo, FMT_NEED_MORE_DATA);
				}
				
				if (len > 0)
				{
					value = (text *) palloc(len + VARHDRSZ);
					SET_VARSIZE(value, len + VARHDRSZ);

					memcpy(VARDATA(value), data_buf + data_cur + sizeof(len), len);
					
					myData->nulls[i] = false;
					myData->values[i] = PointerGetDatum(value);
				}

				attr_len = len + sizeof(len);
				
				break;
			}
			
			default:
				elog(ERROR, "formatter_import: unsupported datatype");
				break;
		}	
		
		/* add byte length of last attribute to the temporary cursor */
		data_cur += attr_len;
		
	}
	/* ======================================================================= */

	MemoryContextSwitchTo(oldcontext);

	FORMATTER_SET_DATACURSOR(fcinfo, data_cur);

	tuple = heap_form_tuple(tupdesc, myData->values, myData->nulls);

	/* hack... pass tuple here. don't free prev tuple - the executor does it  */
	((FormatterData*) fcinfo->context)->fmt_tuple = tuple;
	
	FORMATTER_RETURN_TUPLE(tuple);
}
Datum
#else  // _MSC_VER
PGDLLEXPORT Datum
#endif
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 = funcctx->call_cntr;
    max_calls = funcctx->max_calls;
    tuple_desc = funcctx->tuple_desc;
    result_tuples = (General_path_element_t*) funcctx->user_fctx;

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

        /**********************************************************************/
        /*                          MODIFY AS NEEDED                          */
        // OUT seq INTEGER,
        // OUT path_seq INTEGER,
        // OUT 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);
    }
}
Exemple #21
0
Datum
normal_rand(PG_FUNCTION_ARGS)
{
	FuncCallContext *funcctx;
	int			call_cntr;
	int			max_calls;
	normal_rand_fctx *fctx;
	float8		mean;
	float8		stddev;
	float8		carry_val;
	bool		use_carry;
	MemoryContext oldcontext;

	/* stuff done only on the first call of the function */
	if (SRF_IS_FIRSTCALL())
	{
		/* 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);

		/* total number of tuples to be returned */
		funcctx->max_calls = PG_GETARG_UINT32(0);

		/* allocate memory for user context */
		fctx = (normal_rand_fctx *) palloc(sizeof(normal_rand_fctx));

		/*
		 * Use fctx to keep track of upper and lower bounds from call to call.
		 * It will also be used to carry over the spare value we get from the
		 * Box-Muller algorithm so that we only actually calculate a new value
		 * every other call.
		 */
		fctx->mean = PG_GETARG_FLOAT8(1);
		fctx->stddev = PG_GETARG_FLOAT8(2);
		fctx->carry_val = 0;
		fctx->use_carry = false;

		funcctx->user_fctx = fctx;

		MemoryContextSwitchTo(oldcontext);
	}

	/* stuff done on every call of the function */
	funcctx = SRF_PERCALL_SETUP();

	call_cntr = funcctx->call_cntr;
	max_calls = funcctx->max_calls;
	fctx = funcctx->user_fctx;
	mean = fctx->mean;
	stddev = fctx->stddev;
	carry_val = fctx->carry_val;
	use_carry = fctx->use_carry;

	if (call_cntr < max_calls)	/* do when there is more left to send */
	{
		float8		result;

		if (use_carry)
		{
			/*
			 * reset use_carry and use second value obtained on last pass
			 */
			fctx->use_carry = false;
			result = carry_val;
		}
		else
		{
			float8		normval_1;
			float8		normval_2;

			/* Get the next two normal values */
			get_normal_pair(&normval_1, &normval_2);

			/* use the first */
			result = mean + (stddev * normval_1);

			/* and save the second */
			fctx->carry_val = mean + (stddev * normval_2);
			fctx->use_carry = true;
		}

		/* send the result */
		SRF_RETURN_NEXT(funcctx, Float8GetDatum(result));
	}
	else
		/* do when there is no more left */
		SRF_RETURN_DONE(funcctx);
}
Exemple #22
0
static int compute_trsp(
    char* sql,
    int dovertex,
    long start_id,
    double start_pos,
    long end_id,
    double end_pos,
    bool directed, 
    bool has_reverse_cost,
    char* restrict_sql,
    path_element_t **path,
    uint32_t *path_count) 
{

  int SPIcode;
  SPIPlanPtr SPIplan;
  Portal SPIportal;
  bool moredata = TRUE;
  size_t ntuples;

  edge_t *edges = NULL;
  size_t total_tuples = 0;
#ifndef _MSC_VER
  edge_columns_t edge_columns = {.id= -1, .source= -1, .target= -1, 
                                 .cost= -1, .reverse_cost= -1};
#else // _MSC_VER
  edge_columns_t edge_columns = {-1, -1, -1, -1, -1};
#endif //_MSC_VER
  restrict_t *restricts = NULL;
  size_t total_restrict_tuples = 0;

#ifndef _MSC_VER
  restrict_columns_t restrict_columns = {.target_id= -1, .via_path= -1,
                                 .to_cost= -1};
#else // _MSC_VER
  restrict_columns_t restrict_columns = {-1, -1, -1};
#endif //_MSC_VER

  long v_max_id=0;
  long v_min_id=INT_MAX;

  /* track if start and end are both in edge tuples */
  int s_count = 0;
  int t_count = 0;

  char *err_msg;
  int ret = -1;
  uint32_t z;

  PGR_DBG("start turn_restrict_shortest_path\n");
        
  SPIcode = SPI_connect();
  if (SPIcode  != SPI_OK_CONNECT) {
      elog(ERROR, "turn_restrict_shortest_path: couldn't open a connection to SPI");
      return -1;
  }

  SPIplan = SPI_prepare(sql, 0, NULL);
  if (SPIplan  == NULL) {
      elog(ERROR, "turn_restrict_shortest_path: couldn't create query plan via SPI");
      return -1;
  }

  if ((SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true)) == NULL) {
      elog(ERROR, "turn_restrict_shortest_path: SPI_cursor_open('%s') returns NULL", sql);
      return -1;
  }

  while (moredata == TRUE) {
      //PGR_DBG("calling SPI_cursor_fetch");
      SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);

      if (SPI_tuptable == NULL) {
          elog(ERROR, "SPI_tuptable is NULL");
          return finish(SPIcode, -1);
      }

      if (edge_columns.id == -1) {
          if (fetch_edge_columns(SPI_tuptable, &edge_columns, 
                                 has_reverse_cost) == -1)
	        return finish(SPIcode, ret);
      }

      ntuples = SPI_processed;

      //PGR_DBG("Reading edges: %i - %i", total_tuples, total_tuples+ntuples);

      total_tuples += ntuples;

      if (ntuples > 0) {
          if (!edges)
            edges = palloc(total_tuples * sizeof(edge_t));
          else
            edges = repalloc(edges, total_tuples * sizeof(edge_t));

          if (edges == NULL) {
              elog(ERROR, "Out of memory");
              return finish(SPIcode, ret);	  
          }

          uint32_t t;
          SPITupleTable *tuptable = SPI_tuptable;
          TupleDesc tupdesc = SPI_tuptable->tupdesc;
                
          for (t = 0; t < ntuples; t++) {
              //if (t%100 == 0) { PGR_DBG("    t: %i", t); }
              HeapTuple tuple = tuptable->vals[t];
              fetch_edge(&tuple, &tupdesc, &edge_columns, 
                         &edges[total_tuples - ntuples + t]);
          }
          //PGR_DBG("calling SPI_freetuptable");
          SPI_freetuptable(tuptable);
          //PGR_DBG("back from SPI_freetuptable");
      } 
      else {
          moredata = FALSE;
      }
  }
  SPI_cursor_close(SPIportal);

  //defining min and max vertex id
      
  //PGR_DBG("Total %i edge tuples", total_tuples);
    
  for(z=0; z<total_tuples; z++) {
    if(edges[z].source<v_min_id)
      v_min_id=edges[z].source;
  
    if(edges[z].source>v_max_id)
      v_max_id=edges[z].source;
		            
    if(edges[z].target<v_min_id)
      v_min_id=edges[z].target;

    if(edges[z].target>v_max_id)
      v_max_id=edges[z].target;      
								        
    //PGR_DBG("%i <-> %i", v_min_id, v_max_id);
							
  }
	
  //::::::::::::::::::::::::::::::::::::  
  //:: reducing vertex id (renumbering)
  //::::::::::::::::::::::::::::::::::::
  for(z=0; z<total_tuples; z++) {
    //check if edges[] contains source and target
    if (dovertex) {
        if(edges[z].source == start_id || edges[z].target == start_id)
          ++s_count;
        if(edges[z].source == end_id || edges[z].target == end_id)
          ++t_count;
    }
    else {
        if(edges[z].id == start_id)
          ++s_count;
        if(edges[z].id == end_id)
          ++t_count;
    }

    edges[z].source-=v_min_id;
    edges[z].target-=v_min_id;
    edges[z].cost = edges[z].cost;
    //PGR_DBG("edgeID: %i SRc:%i - %i, cost: %f", edges[z].id,edges[z].source, edges[z].target,edges[z].cost);      
    
  }

  PGR_DBG("Min vertex id: %ld , Max vid: %ld",v_min_id,v_max_id);
  PGR_DBG("Total %ld edge tuples", total_tuples);

  if(s_count == 0) {
    elog(ERROR, "Start id was not found.");
    return -1;
  }
      
  if(t_count == 0) {
    elog(ERROR, "Target id was not found.");
    return -1;
  }
  
  if (dovertex) {
      start_id -= v_min_id;
      end_id   -= v_min_id;
  }
  
  PGR_DBG("Fetching restriction tuples\n");
        
  if (restrict_sql == NULL) {
      PGR_DBG("Sql for restrictions is null.");
  }
  else {
      SPIplan = SPI_prepare(restrict_sql, 0, NULL);
      if (SPIplan  == NULL) {
          elog(ERROR, "turn_restrict_shortest_path: couldn't create query plan via SPI");
          return -1;
      }

      if ((SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true)) == NULL) {
          elog(ERROR, "turn_restrict_shortest_path: SPI_cursor_open('%s') returns NULL", restrict_sql);
          return -1;
      }

      moredata = TRUE;
      while (moredata == TRUE) {
          SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);

          if (restrict_columns.target_id == -1) {
              if (fetch_restrict_columns(SPI_tuptable, &restrict_columns) == -1) {
                PGR_DBG("fetch_restrict_columns failed!");
                return finish(SPIcode, ret);
              }
          }

          ntuples = SPI_processed;
          total_restrict_tuples += ntuples;

          //PGR_DBG("Reading Restrictions: %i", total_restrict_tuples);

          if (ntuples > 0) {
              if (!restricts)
                restricts = palloc(total_restrict_tuples * sizeof(restrict_t));
              else
                restricts = repalloc(restricts, total_restrict_tuples * sizeof(restrict_t));

              if (restricts == NULL) {
                  elog(ERROR, "Out of memory");
                  return finish(SPIcode, ret);
              }

              uint32_t t;
              SPITupleTable *tuptable = SPI_tuptable;
              TupleDesc tupdesc = SPI_tuptable->tupdesc;

              for (t = 0; t < ntuples; t++) {
                  HeapTuple tuple = tuptable->vals[t];
                  fetch_restrict(&tuple, &tupdesc, &restrict_columns,
                             &restricts[total_restrict_tuples - ntuples + t]);
              }
              SPI_freetuptable(tuptable);
          }
          else {
              moredata = FALSE;
          }
      }
      SPI_cursor_close(SPIportal);

  }

#ifdef DEBUG_OFF
    int t;
    for (t=0; t<total_restrict_tuples; t++) {
        PGR_DBG("restricts: %.2f, %i, %i, %i, %i, %i, %i", restricts[t].to_cost, restricts[t].target_id, restricts[t].via[0], restricts[t].via[1], restricts[t].via[2], restricts[t].via[3], restricts[t].via[4]);
    }
#endif

  PGR_DBG("Total %ld restriction tuples", total_restrict_tuples);

  if (dovertex) {
      PGR_DBG("Calling trsp_node_wrapper\n");
      /** hack always returns 0 -1 when installed on EDB VC++ 64-bit without this **/
      #if defined(__MINGW64__) 
      //  elog(NOTICE,"Calling trsp_node_wrapper\n");
      #endif
      ret = trsp_node_wrapper(edges, (uint32_t)total_tuples, 
                        restricts, (uint32_t)total_restrict_tuples,
                        start_id, end_id,
                        directed, has_reverse_cost,
                        path, path_count, &err_msg);
  }
  else {
      PGR_DBG("Calling trsp_edge_wrapper\n");
      ret = trsp_edge_wrapper(edges, (uint32_t)total_tuples, 
                        restricts, (uint32_t)total_restrict_tuples,
                        start_id, start_pos, end_id, end_pos,
                        directed, has_reverse_cost,
                        path, path_count, &err_msg);
  }

  PGR_DBG("Message received from inside:");
  PGR_DBG("%s",err_msg);

  //PGR_DBG("SIZE %i\n",*path_count);

  //::::::::::::::::::::::::::::::::
  //:: restoring original vertex id
  //::::::::::::::::::::::::::::::::
  for(z=0;z<*path_count;z++) {
    //PGR_DBG("vetex %i\n",(*path)[z].vertex_id);
    if (z || (*path)[z].vertex_id != -1)
        (*path)[z].vertex_id+=v_min_id;
  }

  PGR_DBG("ret = %i\n", ret);

  PGR_DBG("*path_count = %i\n", *path_count);

  if (ret < 0)
    {
      //elog(ERROR, "Error computing path: %s", err_msg);
      ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED), 
        errmsg("Error computing path: %s", err_msg)));
    } 
    
  return finish(SPIcode, ret);
}



PG_FUNCTION_INFO_V1(turn_restrict_shortest_path_vertex);
PGDLLEXPORT Datum
turn_restrict_shortest_path_vertex(PG_FUNCTION_ARGS)
{
	
  FuncCallContext     *funcctx;
  uint32_t                  call_cntr;
  uint32_t                  max_calls;
  TupleDesc            tuple_desc;
  path_element_t      *path;
  char *               sql;


  // stuff done only on the first call of the function 
  if (SRF_IS_FIRSTCALL()) {
      MemoryContext   oldcontext;
      uint32_t path_count = 0;

      int ret = -1;
      if (ret == -1) {}; // to avoid warning set but not used

      int i;

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

      // verify that the first 5 args are not NULL
      for (i=0; i<5; i++)
        if(PG_ARGISNULL(i)) {
            elog(ERROR, "turn_restrict_shortest_path(): Argument %i may not be NULL", i+1);
        }
      
      if (PG_ARGISNULL(5))
        sql = NULL;
      else {
        sql = text2char(PG_GETARG_TEXT_P(5));
        if (strlen(sql) == 0)
            sql = NULL;
      }

	  PGR_DBG("Calling compute_trsp");


      ret =

 compute_trsp(text2char(PG_GETARG_TEXT_P(0)),
                                   1, // do vertex
                                   PG_GETARG_INT32(1),
                                   0.5,
                                   PG_GETARG_INT32(2),
                                   0.5,
                                   PG_GETARG_BOOL(3),
                                   PG_GETARG_BOOL(4), 
                                   sql,
                                   &path, &path_count);
#ifdef DEBUG
	double total_cost = 0;
      PGR_DBG("Ret is %i", ret);
      if (ret >= 0) 
        {
          int i;
          for (i = 0; i < path_count; i++) 
            {
         //     PGR_DBG("Step %i vertex_id  %i ", i, path[i].vertex_id);
           //   PGR_DBG("        edge_id    %i ", path[i].edge_id);
             // PGR_DBG("        cost       %f ", path[i].cost);
              total_cost+=path[i].cost;
            }
        }
        PGR_DBG("Total cost is: %f",total_cost);
#endif

      // total number of tuples to be returned 
      funcctx->max_calls = path_count;
      funcctx->user_fctx = path;

      funcctx->tuple_desc = 
        BlessTupleDesc(RelationNameGetTupleDesc("pgr_costResult"));

      MemoryContextSwitchTo(oldcontext);
    }

  // stuff done on every call of the function 
  funcctx = SRF_PERCALL_SETUP();

  call_cntr = (uint32_t)funcctx->call_cntr;
  max_calls = (uint32_t)funcctx->max_calls;
  tuple_desc = funcctx->tuple_desc;
  path = (path_element_t*) funcctx->user_fctx;

  if (call_cntr < max_calls)    // do when there is more left to send 
    {
      HeapTuple    tuple;
      Datum        result;
      Datum *values;
      bool* nulls;

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

      values[0] = Int32GetDatum(call_cntr);
      nulls[0] = false;
      values[1] = Int32GetDatum(path[call_cntr].vertex_id);
      nulls[1] = false;
      values[2] = Int32GetDatum(path[call_cntr].edge_id);
      nulls[2] = false;
      values[3] = Float8GetDatum(path[call_cntr].cost);
      nulls[3] = false;
		      
      tuple = heap_form_tuple(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 
    {
      PGR_DBG("Going to free path");
      if (path) free(path);
      SRF_RETURN_DONE(funcctx);
    }
}

PG_FUNCTION_INFO_V1(turn_restrict_shortest_path_edge);
PGDLLEXPORT Datum
turn_restrict_shortest_path_edge(PG_FUNCTION_ARGS)
{
	
  FuncCallContext     *funcctx;
  uint32_t                  call_cntr;
  uint32_t                  max_calls;
  TupleDesc            tuple_desc;
  path_element_t      *path;
  char *               sql;

  // stuff done only on the first call of the function 
  if (SRF_IS_FIRSTCALL()) {
      MemoryContext   oldcontext;
      uint32_t path_count = 0;
#ifdef DEBUG
      int ret = -1;
#endif
      int i;
      double s_pos;
      double e_pos;

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

      // verify that the first 5 args are not NULL
      for (i=0; i<7; i++) {
        if(i==2 || i==4) continue;
        if(PG_ARGISNULL(i)) {
            elog(ERROR, "turn_restrict_shortest_path(): Argument %i may not be NULL", i+1);
        }
      }

      if (PG_ARGISNULL(2))
        s_pos = 0.5;
      else {
        s_pos = PG_GETARG_FLOAT8(2);
        if (s_pos < 0.0) s_pos = 0.5;
        if (s_pos > 1.0) s_pos = 0.5;
      }
      
      if (PG_ARGISNULL(4))
        e_pos = 0.5;
      else {
        e_pos = PG_GETARG_FLOAT8(4);
        if (e_pos < 0.0) e_pos = 0.5;
        if (e_pos > 1.0) e_pos = 0.5;
      }
      
      if (PG_ARGISNULL(7))
        sql = NULL;
      else {
        sql = text2char(PG_GETARG_TEXT_P(7));
        if (strlen(sql) == 0)
            sql = NULL;
      }

	  PGR_DBG("Calling compute_trsp");

#ifdef DEBUG
      ret =
#endif
         compute_trsp(text2char(PG_GETARG_TEXT_P(0)),
                                   0,  //sdo edge
                                   PG_GETARG_INT32(1),
                                   s_pos,
                                   PG_GETARG_INT32(3),
                                   e_pos,
                                   PG_GETARG_BOOL(5),
                                   PG_GETARG_BOOL(6), 
                                   sql,
                                   &path, &path_count);
#ifdef DEBUG
	double total_cost = 0;
      PGR_DBG("Ret is %i", ret);
      if (ret >= 0) 
        {
          int i;
          for (i = 0; i < path_count; i++) 
            {
         //     PGR_DBG("Step %i vertex_id  %i ", i, path[i].vertex_id);
           //   PGR_DBG("        edge_id    %i ", path[i].edge_id);
             // PGR_DBG("        cost       %f ", path[i].cost);
              total_cost+=path[i].cost;
            }
        }
        PGR_DBG("Total cost is: %f",total_cost);
#endif

      // total number of tuples to be returned 
      funcctx->max_calls = path_count;
      funcctx->user_fctx = path;

      funcctx->tuple_desc = 
        BlessTupleDesc(RelationNameGetTupleDesc("pgr_costResult"));

      MemoryContextSwitchTo(oldcontext);
    }

  // stuff done on every call of the function 
  funcctx = SRF_PERCALL_SETUP();

  call_cntr = (uint32_t)funcctx->call_cntr;
  max_calls = (uint32_t)funcctx->max_calls;
  tuple_desc = funcctx->tuple_desc;
  path = (path_element_t*) funcctx->user_fctx;

  if (call_cntr < max_calls)    // do when there is more left to send 
    {
      HeapTuple    tuple;
      Datum        result;
      Datum *values;
      bool* nulls;

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

      values[0] = Int32GetDatum(call_cntr);
      nulls[0] = false;
      values[1] = Int32GetDatum(path[call_cntr].vertex_id);
      nulls[1] = false;
      values[2] = Int32GetDatum(path[call_cntr].edge_id);
      nulls[2] = false;
      values[3] = Float8GetDatum(path[call_cntr].cost);
      nulls[3] = false;
		      
      tuple = heap_form_tuple(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 
    {
      PGR_DBG("Going to free path");
      if (path) free(path);
      SRF_RETURN_DONE(funcctx);
    }
}