Example #1
0
/*-----------------------------------------------------------------------------
 * array_positions :
 *			return an array of positions of a value in an array.
 *
 * IS NOT DISTINCT FROM semantics are used for comparisons.  Returns NULL when
 * the input array is NULL.  When the value is not found in the array, returns
 * an empty array.
 *
 * This is not strict so we have to test for null inputs explicitly.
 *-----------------------------------------------------------------------------
 */
Datum
array_positions(PG_FUNCTION_ARGS)
{
	ArrayType  *array;
	Oid			collation = PG_GET_COLLATION();
	Oid			element_type;
	Datum		searched_element,
				value;
	bool		isnull;
	int			position;
	TypeCacheEntry *typentry;
	ArrayMetaState *my_extra;
	bool		null_search;
	ArrayIterator array_iterator;
	ArrayBuildState *astate = NULL;

	if (PG_ARGISNULL(0))
		PG_RETURN_NULL();

	array = PG_GETARG_ARRAYTYPE_P(0);
	element_type = ARR_ELEMTYPE(array);

	position = (ARR_LBOUND(array))[0] - 1;

	/*
	 * We refuse to search for elements in multi-dimensional arrays, since we
	 * have no good way to report the element's location in the array.
	 */
	if (ARR_NDIM(array) > 1)
		ereport(ERROR,
				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
				 errmsg("searching for elements in multidimensional arrays is not supported")));

	astate = initArrayResult(INT4OID, CurrentMemoryContext, false);

	if (PG_ARGISNULL(1))
	{
		/* fast return when the array doesn't have nulls */
		if (!array_contains_nulls(array))
			PG_RETURN_DATUM(makeArrayResult(astate, CurrentMemoryContext));
		searched_element = (Datum) 0;
		null_search = true;
	}
	else
	{
		searched_element = PG_GETARG_DATUM(1);
		null_search = false;
	}

	/*
	 * We arrange to look up type info for array_create_iterator only once per
	 * series of calls, assuming the element type doesn't change underneath
	 * us.
	 */
	my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
	if (my_extra == NULL)
	{
		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
													  sizeof(ArrayMetaState));
		my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
		my_extra->element_type = ~element_type;
	}

	if (my_extra->element_type != element_type)
	{
		get_typlenbyvalalign(element_type,
							 &my_extra->typlen,
							 &my_extra->typbyval,
							 &my_extra->typalign);

		typentry = lookup_type_cache(element_type, TYPECACHE_EQ_OPR_FINFO);

		if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_FUNCTION),
				errmsg("could not identify an equality operator for type %s",
					   format_type_be(element_type))));

		my_extra->element_type = element_type;
		fmgr_info_cxt(typentry->eq_opr_finfo.fn_oid, &my_extra->proc,
					  fcinfo->flinfo->fn_mcxt);
	}

	/*
	 * Accumulate each array position iff the element matches the given
	 * element.
	 */
	array_iterator = array_create_iterator(array, 0, my_extra);
	while (array_iterate(array_iterator, &value, &isnull))
	{
		position += 1;

		/*
		 * Can't look at the array element's value if it's null; but if we
		 * search for null, we have a hit.
		 */
		if (isnull || null_search)
		{
			if (isnull && null_search)
				astate =
					accumArrayResult(astate, Int32GetDatum(position), false,
									 INT4OID, CurrentMemoryContext);

			continue;
		}

		/* not nulls, so run the operator */
		if (DatumGetBool(FunctionCall2Coll(&my_extra->proc, collation,
										   searched_element, value)))
			astate =
				accumArrayResult(astate, Int32GetDatum(position), false,
								 INT4OID, CurrentMemoryContext);
	}

	array_free_iterator(array_iterator);

	/* Avoid leaking memory when handed toasted input */
	PG_FREE_IF_COPY(array, 0);

	PG_RETURN_DATUM(makeArrayResult(astate, CurrentMemoryContext));
}
/*-----------------------------------------------------------------------------
 * array_push :
 *		push an element onto either end of a one-dimensional array
 *----------------------------------------------------------------------------
 */
Datum
array_push(PG_FUNCTION_ARGS)
{
	ArrayType  *v;
	Datum		newelem;
	bool		isNull;
	int		   *dimv,
			   *lb;
	ArrayType  *result;
	int			indx;
	Oid			element_type;
	int16		typlen;
	bool		typbyval;
	char		typalign;
	Oid			arg0_typeid = get_fn_expr_argtype(fcinfo->flinfo, 0);
	Oid			arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1);
	Oid			arg0_elemid;
	Oid			arg1_elemid;
	ArrayMetaState *my_extra;

	if (arg0_typeid == InvalidOid || arg1_typeid == InvalidOid)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("could not determine input data types")));

	arg0_elemid = get_element_type(arg0_typeid);
	arg1_elemid = get_element_type(arg1_typeid);

	if (arg0_elemid != InvalidOid)
	{
		if (PG_ARGISNULL(0))
			v = construct_empty_array(arg0_elemid);
		else
			v = PG_GETARG_ARRAYTYPE_P(0);
		isNull = PG_ARGISNULL(1);
		if (isNull)
			newelem = (Datum) 0;
		else
			newelem = PG_GETARG_DATUM(1);
	}
	else if (arg1_elemid != InvalidOid)
	{
		if (PG_ARGISNULL(1))
			v = construct_empty_array(arg1_elemid);
		else
			v = PG_GETARG_ARRAYTYPE_P(1);
		isNull = PG_ARGISNULL(0);
		if (isNull)
			newelem = (Datum) 0;
		else
			newelem = PG_GETARG_DATUM(0);
	}
	else
	{
		/* Shouldn't get here given proper type checking in parser */
		ereport(ERROR,
				(errcode(ERRCODE_DATATYPE_MISMATCH),
				 errmsg("neither input type is an array")));
		PG_RETURN_NULL();		/* keep compiler quiet */
	}

	element_type = ARR_ELEMTYPE(v);

	if (ARR_NDIM(v) == 1)
	{
		lb = ARR_LBOUND(v);
		dimv = ARR_DIMS(v);

		if (arg0_elemid != InvalidOid)
		{
			/* append newelem */
			int			ub = dimv[0] + lb[0] - 1;

			indx = ub + 1;
			/* overflow? */
			if (indx < ub)
				ereport(ERROR,
						(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
						 errmsg("integer out of range")));
		}
		else
		{
			/* prepend newelem */
			indx = lb[0] - 1;
			/* overflow? */
			if (indx > lb[0])
				ereport(ERROR,
						(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
						 errmsg("integer out of range")));
		}
	}
	else if (ARR_NDIM(v) == 0)
		indx = 1;
	else
		ereport(ERROR,
				(errcode(ERRCODE_DATA_EXCEPTION),
				 errmsg("argument must be empty or one-dimensional array")));

	/*
	 * We arrange to look up info about element type only once per series of
	 * calls, assuming the element type doesn't change underneath us.
	 */
	my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
	if (my_extra == NULL)
	{
		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
													  sizeof(ArrayMetaState));
		my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
		my_extra->element_type = ~element_type;
	}

	if (my_extra->element_type != element_type)
	{
		/* Get info about element type */
		get_typlenbyvalalign(element_type,
							 &my_extra->typlen,
							 &my_extra->typbyval,
							 &my_extra->typalign);
		my_extra->element_type = element_type;
	}
	typlen = my_extra->typlen;
	typbyval = my_extra->typbyval;
	typalign = my_extra->typalign;

	result = array_set(v, 1, &indx, newelem, isNull,
					   -1, typlen, typbyval, typalign);

	/*
	 * Readjust result's LB to match the input's.  This does nothing in the
	 * append case, but it's the simplest way to implement the prepend case.
	 */
	if (ARR_NDIM(v) == 1)
		ARR_LBOUND(result)[0] = ARR_LBOUND(v)[0];

	PG_RETURN_ARRAYTYPE_P(result);
}
Example #3
0
Datum
alpine_miner_lr_ca_he_de_accum(PG_FUNCTION_ARGS)
{

        ArrayType  *beta_arg, *columns_arg, *result;
        float8     *beta_data, *columns_data, *result_data;
	int         beta_count, columns_count, result_count;
        int         size;

	bool add_intercept_arg;
	double weight_arg;
	int y_arg;

	double fitness = 0.0;
	double gx = 0.0;
	double pi = 0.0;
	if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3) || PG_ARGISNULL(4) || PG_ARGISNULL(5)){
		PG_RETURN_NULL();
	}
	result = PG_GETARG_ARRAYTYPE_P(0);
        beta_arg = PG_GETARG_ARRAYTYPE_P(1);
        columns_arg = PG_GETARG_ARRAYTYPE_P(2);
	add_intercept_arg = PG_GETARG_BOOL(3);
	weight_arg = PG_GETARG_FLOAT8(4);
	y_arg = PG_GETARG_INT32(5);

	result_data = (float8*) ARR_DATA_PTR(result);
	beta_data = (float8*) ARR_DATA_PTR(beta_arg);
	columns_data = (float8*) ARR_DATA_PTR(columns_arg);
	
	result_count = ARR_DIMS(result)[0];
	beta_count = ARR_DIMS(beta_arg)[0];
	columns_count = ARR_DIMS(columns_arg)[0];
//	float8 * column_array_data = (float8*) ARR_DATA_PTR(column_array);
	if (result_count == 1){
		result_count = beta_count *(beta_count+1)/2 + beta_count + 1;
       	 	size =  result_count * sizeof(float8) + ARR_OVERHEAD_NONULLS(1);
        	result = (ArrayType *) palloc(size);
	        SET_VARSIZE(result, size);
       	 	result->ndim = 1;
        	result->dataoffset = 0;
        	result->elemtype = FLOAT8OID;
        	ARR_DIMS(result)[0] = result_count;
        	ARR_LBOUND(result)[0] = 1;
		result_data = (float8*) ARR_DATA_PTR(result);
        	memset(result_data, 0,  result_count * sizeof(float8));
	}

	pi = alpine_miner_compute_pi(beta_data, beta_count, columns_data, columns_count, add_intercept_arg);

	alpine_miner_compute_hessian(beta_count,beta_data,columns_data, result_data
		,weight_arg, add_intercept_arg,  pi);

	alpine_miner_compute_derivative(columns_count,columns_data, &result_data[beta_count *(beta_count+1)/2]
		,weight_arg, y_arg, add_intercept_arg, pi);

	if (y_arg == 1)
	{
		fitness = log(pi);
	}
	else
	{
		fitness = log(1.0 - pi);
	}
	fitness *= weight_arg;
	result_data[result_count - 1] = fitness + result_data[result_count - 1];

        PG_RETURN_ARRAYTYPE_P(result);
}
Example #4
0
Datum
#else  // _MSC_VER
PGDLLEXPORT Datum
#endif
MY_FUNCTION_NAME(PG_FUNCTION_ARGS) {
    FuncCallContext     *funcctx;
    uint32_t            call_cntr;
    uint32_t            max_calls;
    TupleDesc           tuple_desc;

    /**************************************************************************/
    /*                          MODIFY AS NEEDED                              */
    /*                                                                        */
    MY_RETURN_VALUE_TYPE  *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                          */
        /*
           MY_QUERY_LINE1
         **********************************************************************/

        PGR_DBG("Initializing arrays");
        int64_t* end_vidsArr;
        size_t size_end_vidsArr;
        end_vidsArr = (int64_t*) pgr_get_bigIntArray(&size_end_vidsArr, PG_GETARG_ARRAYTYPE_P(2));
        PGR_DBG("targetsArr size %ld ", size_end_vidsArr);

        PGR_DBG("Calling process");
        // Code standard:
        // Use same order as in the query
        // Pass the array and it's size on the same line
        process(
                pgr_text2char(PG_GETARG_TEXT_P(0)),
                PG_GETARG_INT64(1),
                end_vidsArr, size_end_vidsArr,
                PG_GETARG_BOOL(3),
                &result_tuples,
                &result_count);

        // while developing leave the message as a reminder
        PGR_DBG("Cleaning arrays using free(<array-name>)");
        free(end_vidsArr);
        /*                                                                             */
        /*******************************************************************************/

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

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

        /*******************************************************************************/
        /*                          MODIFY!!!!!                                        */
        /*  This has to match you ouput otherwise the server crashes                   */
        /*
           MY_QUERY_LINE2
         ********************************************************************************/


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

        size_t i;
        for(i = 0; i < 8; ++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].start_id);
        values[3] = Int64GetDatum(result_tuples[call_cntr].end_id);
        values[4] = Int64GetDatum(result_tuples[call_cntr].node);
        values[5] = Int64GetDatum(result_tuples[call_cntr].edge);
        values[6] = Float8GetDatum(result_tuples[call_cntr].cost);
        values[7] = 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);
    }
}
Example #5
0
File: plda.c Project: dcking/madlib
Datum sampleNewTopics(PG_FUNCTION_ARGS)
{
	int32 i, widx, wtopic, rtopic;

	ArrayType * doc_arr = PG_GETARG_ARRAYTYPE_P(0);
	ArrayType * topics_arr = PG_GETARG_ARRAYTYPE_P(1);
	ArrayType * topic_d_arr = PG_GETARG_ARRAYTYPE_P(2);
	ArrayType * global_count_arr = PG_GETARG_ARRAYTYPE_P(3);
	ArrayType * topic_counts_arr = PG_GETARG_ARRAYTYPE_P(4);
	int32 num_topics = PG_GETARG_INT32(5);
	int32 dsize = PG_GETARG_INT32(6);
	float8 alpha = PG_GETARG_FLOAT8(7);
	float8 eta = PG_GETARG_FLOAT8(8);

	if (ARR_NULLBITMAP(doc_arr) || ARR_NDIM(doc_arr) != 1 || 
	    ARR_ELEMTYPE(doc_arr) != INT4OID ||
	    ARR_NDIM(topics_arr) != 1 || ARR_ELEMTYPE(topics_arr) != INT4OID ||
	    ARR_NULLBITMAP(topic_d_arr) || ARR_NDIM(topic_d_arr) != 1 || 
	    ARR_ELEMTYPE(topic_d_arr) != INT4OID ||
	    ARR_NULLBITMAP(global_count_arr) || ARR_NDIM(global_count_arr) != 1
	    || ARR_ELEMTYPE(global_count_arr) != INT4OID ||
	    ARR_NULLBITMAP(topic_counts_arr) || ARR_NDIM(topic_counts_arr) != 1
	    || ARR_ELEMTYPE(topic_counts_arr) != INT4OID)
		ereport(ERROR,
		       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
			errmsg("function \"%s\" called with invalid parameters",
			       format_procedure(fcinfo->flinfo->fn_oid))));

	// the document array
	int32 * doc = (int32 *)ARR_DATA_PTR(doc_arr);
	int32 len = ARR_DIMS(doc_arr)[0];

	// array giving topic assignment to each word in document
	int32 * topics = (int32 *)ARR_DATA_PTR(topics_arr);

	// distribution of topics in document
	int32 * topic_d = (int32 *)ARR_DATA_PTR(topic_d_arr);

	// the word-topic count matrix
	int32 * global_count = (int32 *)ARR_DATA_PTR(global_count_arr);

	// total number of words assigned to each topic in the whole corpus
	int32 * topic_counts = (int32 *)ARR_DATA_PTR(topic_counts_arr);

	ArrayType * ret_topics_arr, * ret_topic_d_arr;
	int32 * ret_topics, * ret_topic_d;

	Datum * arr1 = palloc0(len * sizeof(Datum));
	ret_topics_arr = construct_array(arr1,len,INT4OID,4,true,'i');
	ret_topics = (int32 *)ARR_DATA_PTR(ret_topics_arr);

	Datum * arr2 = palloc0(num_topics * sizeof(Datum));
	ret_topic_d_arr = construct_array(arr2,num_topics,INT4OID,4,true,'i');
	ret_topic_d = (int32 *)ARR_DATA_PTR(ret_topic_d_arr);

	for (i=0; i!=len; i++) {
		widx = doc[i];

		if (widx < 1 || widx > dsize)
		     ereport
		      (ERROR,
		       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
			errmsg("function \"%s\" called with invalid parameters",
			       format_procedure(fcinfo->flinfo->fn_oid))));

		wtopic = topics[i];
		rtopic = sampleTopic(num_topics,widx,wtopic,global_count,
				     topic_d,topic_counts,alpha,eta);

		// <sampleNewTopics error checking> 

		ret_topics[i] = rtopic;
		ret_topic_d[rtopic-1]++;
	}

	Datum values[2];
	values[0] = PointerGetDatum(ret_topics_arr);
	values[1] = PointerGetDatum(ret_topic_d_arr);

	TupleDesc tuple;
	if (get_call_result_type(fcinfo, NULL, &tuple) != TYPEFUNC_COMPOSITE)
		ereport(ERROR,
			(errcode( ERRCODE_FEATURE_NOT_SUPPORTED ),
			 errmsg( "function returning record called in context "
				 "that cannot accept type record" )));
	tuple = BlessTupleDesc(tuple);

	bool * isnulls = palloc0(2 * sizeof(bool));
	HeapTuple ret = heap_form_tuple(tuple, values, isnulls);

	if (isnulls[0] || isnulls[1])
		ereport(ERROR,
			(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
			 errmsg("function \"%s\" produced null results",
				format_procedure(fcinfo->flinfo->fn_oid),i)));

	PG_RETURN_DATUM(HeapTupleGetDatum(ret));
}
Datum generate_sparse_vector(PG_FUNCTION_ARGS)
{
    SvecType    *output_sfv;
    int16_t     typlen;
	bool        typbyval;
	char        typalign;
	bool        *nulls;

	if (PG_NARGS() != 3)
		elog(ERROR, "Invalid number of arguments.");

	ArrayType   *term_index = PG_GETARG_ARRAYTYPE_P(0);
	ArrayType   *term_count = PG_GETARG_ARRAYTYPE_P(1);

	int64_t dict_size = PG_GETARG_INT64(2);

	/* Check if arrays have null entries */
	if (ARR_HASNULL(term_index) || ARR_HASNULL(term_count))
		elog(ERROR, "One or both of the argument arrays has one or more null entries.");

	if (dict_size <= 0)
		elog(ERROR, "Dictionary size cannot be zero or negative.");

	/* Check if any of the argument arrays is empty */
	if ((ARR_NDIM(term_index) == 0) || (ARR_NDIM(term_count) == 0))
		elog(ERROR, "One or more argument arrays is empty.");

	int term_index_nelems = ARR_DIMS(term_index)[0];
	int term_count_nelems = ARR_DIMS(term_count)[0];


	/* If no. of elements in the arrays are not equal, throw an error */
	if (term_index_nelems != term_count_nelems)
		elog(ERROR, "No. of elements in the argument arrays are not equal.");

	Datum *term_index_data;
	Datum *term_count_data;

	/* Deconstruct the arrays */
	get_typlenbyvalalign(INT8OID, &typlen, &typbyval, &typalign);
	deconstruct_array(term_index, INT8OID, typlen, typbyval, typalign,
	                  &term_index_data, &nulls, &term_index_nelems);

	get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
	deconstruct_array(term_count, FLOAT8OID, typlen, typbyval, typalign,
	                  &term_count_data, &nulls, &term_count_nelems);

	/* Check if term index array has indexes in proper order or not */
	for(int i = 0; i < term_index_nelems; i++)
	{
		if (DatumGetInt64(term_index_data[i]) < 0 ||
                DatumGetInt64(term_index_data[i]) >= dict_size)
			elog(ERROR, "Term indexes must range from 0 to total number of elements in the dictonary - 1.");
	}
        

    float8 *histogram = (float8 *)palloc0(sizeof(float8) * dict_size);
    for (int k = 0; k < dict_size; k++)
    {
        histogram[k] = 0;
    }
    for (int i = 0; i < term_index_nelems; i++)
    {
        uint64_t idx = DatumGetInt64(term_index_data[i]);
        histogram[idx] += DatumGetFloat8(term_count_data[i]);
    }

    output_sfv = svec_from_float8arr(histogram, dict_size);
    pfree(histogram);

    PG_RETURN_POINTER(output_sfv);
}
Example #7
0
/*
 * pivot_accum() - Pivot and accumulate
 */
static Datum oid_pivot_accum(FunctionCallInfo fcinfo, Oid type)
{
	ArrayType  *data;
	ArrayType  *labels;
	text       *attr;
	int         i;
	
	/* Simple argument validation */
	if (PG_NARGS() != 4)
		ereport(ERROR, 
				(errcode(ERRCODE_DATATYPE_MISMATCH),
				 errmsg("pivot_accum called with %d input arguments",
						PG_NARGS())));
	if (PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3))
	{
		if (PG_ARGISNULL(0))
			PG_RETURN_NULL();
		PG_RETURN_ARRAYTYPE_P(PG_GETARG_ARRAYTYPE_P(0));
	}
    labels = PG_GETARG_ARRAYTYPE_P(1);
	attr   = PG_GETARG_TEXT_P(2);
	
	/* Do nothing if the attr isn't in the labels array. */
	if ((i = pivot_find(labels, attr)) < 0)
	{
		if (PG_ARGISNULL(0))
			PG_RETURN_NULL();
		PG_RETURN_ARRAYTYPE_P(PG_GETARG_ARRAYTYPE_P(0));
	}
	
	/* Get the data array, or make it if null */
	if (!PG_ARGISNULL(0))
	{
		data = PG_GETARG_ARRAYTYPE_P(0);
		Assert(ARR_DIMS(labels)[0] == ARR_DIMS(data)[0]);
	}
	else
	{
		int elsize, size, nelem;

		switch (type) {
			case INT4OID:
				elsize = 4;
				break;
			case INT8OID:
			case FLOAT8OID:
				elsize = 8; 
				break;
			default:
				elsize = 0;  /* Fixes complier warnings */
				Assert(false);
		}
		nelem = ARR_DIMS(labels)[0];
		size = nelem * elsize + ARR_OVERHEAD_NONULLS(1);
		data = (ArrayType *) palloc(size);
		SET_VARSIZE(data, size);
		data->ndim = 1;
		data->dataoffset = 0;
		data->elemtype = type;
		ARR_DIMS(data)[0] = nelem;
		ARR_LBOUND(data)[0] = 1;
		memset(ARR_DATA_PTR(data), 0, nelem * elsize);
	}
	
	
	/*   
	 * Should we think about upconverting the arrays? Or is the assumption that 
	 * the pivot isn't usually doing much aggregation?
	 */
	switch (type) {
		case INT4OID:
		{
			int32 *datap = (int32*) ARR_DATA_PTR(data);
			int32  value = PG_GETARG_INT32(3);
			datap[i] += value;
			break;
		}
		case INT8OID:
		{
			int64 *datap = (int64*) ARR_DATA_PTR(data);
			int64  value = PG_GETARG_INT64(3);
			datap[i] += value;
			break;
		}
		case FLOAT8OID:
		{
			float8 *datap = (float8*) ARR_DATA_PTR(data);
			float8  value = PG_GETARG_FLOAT8(3);
			datap[i] += value;
			break;
		}
		default:
			Assert(false);
	}
	PG_RETURN_ARRAYTYPE_P(data);
}
Example #8
0
Datum
__vcrf_max_top1_array(PG_FUNCTION_ARGS)
{
        ArrayType  *v1 ;
        // ,
        //                    *v2;
        ArrayType  *result;
        // int                *dims,
                           // *lbs,
        int                        ndims,
                                // nitems,
                                ndatabytes,
                                nbytes;
        int         nitems1;
        // int                *dims1,
        //                    *lbs1,
        //                         ndims1,
        //                         nitems1,
        //                         ndatabytes1;
        // int                *dims2,
                           // *lbs2,
                                // ndims2,
                                // nitems2,
                                // ndatabytes2;
        int                     i;
        // char       *dat1,
        //                    *dat2;
        // bits8      *bitmap1,
        //                    *bitmap2;
        Oid                     element_type;
    // Oid                     element_type1;
    //         Oid                     element_type2;
        int32           dataoffset;

        if (PG_ARGISNULL(0))
                abort();

        v1 = PG_GETARG_ARRAYTYPE_P(0);

        element_type = ARR_ELEMTYPE(v1);

        nitems1 = ARR_DIMS(v1)[1];

        if (nitems1 == 0)
                abort();

        /* new array is the same as v1 for top 1 only !! */
        ndims = 2;
        ndatabytes = 3*sizeof(int);
        dataoffset = 0;                 /* marker for no null bitmap */
        nbytes = ndatabytes + ARR_OVERHEAD_NONULLS(ndims);

        result = (ArrayType *) palloc(nbytes);
        SET_VARSIZE(result, nbytes);
        result->ndim = ndims;
        result->dataoffset = dataoffset;
        result->elemtype = element_type;
        ARR_DIMS(result)[0]=3; /* num elements in first dim */
        ARR_DIMS(result)[1]=1; /* num elements in second dim */
	 /* postgres arrays can be index from any start position eg:
 *            int[-5:14]. this is unlike c, where index always starts at 0 */
        ARR_LBOUND(result)[0]=1; /* index of the first dim starts at .. */
        ARR_LBOUND(result)[1]=1; /* index of second dim starts at ... */

	// do top1 calculation here
	for(i = 0; i < nitems1; i++) {
                  if (i == 0 || ((int*)ARR_DATA_PTR(v1))[0*nitems1+i] >
                                ((int*)ARR_DATA_PTR(v1))[0*nitems1+((int*)ARR_DATA_PTR(result))[0*1+0]]) {
                        ((int*)ARR_DATA_PTR(result))[0*1+0] = i;
                        ((int*)ARR_DATA_PTR(result))[1*1+0] = ((int*)ARR_DATA_PTR(v1))[1*nitems1+i];
                        ((int*)ARR_DATA_PTR(result))[2*1+0] = ((int*)ARR_DATA_PTR(v1))[0*nitems1+i];
                  }
        }
        
        PG_RETURN_ARRAYTYPE_P(result);
}
PGDLLEXPORT Datum
max_flow_many_to_many(PG_FUNCTION_ARGS) {
    FuncCallContext *funcctx;
    TupleDesc tuple_desc;

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


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

        process(
                text_to_cstring(PG_GETARG_TEXT_P(0)),
                PG_GETARG_ARRAYTYPE_P(1),
                PG_GETARG_ARRAYTYPE_P(2),
                text_to_cstring(PG_GETARG_TEXT_P(3)),
                PG_GETARG_BOOL(4),
                &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 = (pgr_flow_t *) funcctx->user_fctx;

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

        /**********************************************************************/
        /*                          MODIFY AS NEEDED                          */
        values = palloc(6 * sizeof(Datum));
        nulls = palloc(6 * sizeof(bool));

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

        values[0] = Int32GetDatum(call_cntr + 1);
        values[1] = Int64GetDatum(result_tuples[call_cntr].edge);
        values[2] = Int64GetDatum(result_tuples[call_cntr].source);
        values[3] = Int64GetDatum(result_tuples[call_cntr].target);
        values[4] = Int64GetDatum(result_tuples[call_cntr].flow);
        values[5] = Int64GetDatum(result_tuples[call_cntr].residual_capacity);
        /**********************************************************************/

        tuple = heap_form_tuple(tuple_desc, values, nulls);
        result = HeapTupleGetDatum(tuple);
        SRF_RETURN_NEXT(funcctx, result);
    } else {
        SRF_RETURN_DONE(funcctx);
    }
}
Datum array_multi_index( PG_FUNCTION_ARGS ) {
	if( PG_ARGISNULL(0) ) {
		PG_RETURN_NULL();
	}
	if( PG_ARGISNULL(1) ) {
		PG_RETURN_NULL();
	}
	
	ArrayType* values = PG_GETARG_ARRAYTYPE_P( 0 );
	ArrayType* indices = PG_GETARG_ARRAYTYPE_P( 1 );

	Oid values_type = ARR_ELEMTYPE( values );
	int16 values_width;
	bool values_passbyvalue;
	char values_alignmentcode;
	Datum* values_content;
	bool* values_nullflags;
	int values_length;
	get_typlenbyvalalign( values_type, &values_width, &values_passbyvalue, &values_alignmentcode );
	deconstruct_array( values, values_type, values_width, values_passbyvalue, values_alignmentcode, &values_content, &values_nullflags, &values_length );

	Oid indices_type = ARR_ELEMTYPE( indices );
	int16 indices_width;
	bool indices_passbyvalue;
	char indices_alignmentcode;
	Datum* indices_content;
	bool* indices_nullflags;
	int indices_length;
	get_typlenbyvalalign( indices_type, &indices_width, &indices_passbyvalue, &indices_alignmentcode );
	deconstruct_array( indices, indices_type, indices_width, indices_passbyvalue, indices_alignmentcode, &indices_content, &indices_nullflags, &indices_length );
	
	Oid results_type = values_type;
	int16 results_width = values_width;
	bool results_passbyvalue = values_passbyvalue;
	char results_alignmentcode = values_alignmentcode;
	Datum* results_content = (Datum *)palloc( sizeof(Datum) * indices_length );
	bool* results_nullflags = (bool *)palloc0( sizeof(bool) * indices_length );
	int results_length = indices_length;
	int i;
	for( i = 0; i < indices_length; ++i ) {
		if( indices_nullflags[i] ) {
			results_content[i] = 0;
			results_nullflags[i] = true;
		} else if( indices_content[i] - 1 >= (long unsigned)values_length ) {
			results_content[i] = 0;
			results_nullflags[i] = true;
		} else {
			results_content[i] = values_content[ indices_content[i] - 1 ];
			results_nullflags[i] = values_nullflags[ indices_content[i] - 1 ];
		}
	}

	int dims[1];
	int lbs[1];
	dims[0] = results_length;
	lbs[0] = 1;
	ArrayType* results = construct_md_array( results_content, results_nullflags, 1, dims, lbs, results_type, results_width, results_passbyvalue, results_alignmentcode );
	pfree( results_content );
	pfree( results_nullflags );
	PG_RETURN_ARRAYTYPE_P( results ); 
}
Example #11
0
Datum
__vcrf_sum_array(PG_FUNCTION_ARGS)
{
	ArrayType  *v1,
			   *v2;
	ArrayType  *result;
    // int         *dims,
    //         *lbs,
	int			ndims,
                // nitems,
				ndatabytes,
				nbytes;
    int         nitems1, nitems2;
    // int         *dims1,
    //         *lbs1,
    //          ndims1,
    //          nitems1,
    //          ndatabytes1;
    // int         *dims2,
    //         *lbs2,
    //          ndims2,
    //          nitems2,
    //          ndatabytes2;
    int          i;
    // char    *dat1,
    //         *dat2;
    // bits8       *bitmap1,
    //         *bitmap2;
    Oid          element_type;
    // Oid          element_type1;
    // Oid          element_type2;
	int32		dataoffset;
    int         spos;

	if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
		abort();

	// pointers to the postgres arrays
	v1 = PG_GETARG_ARRAYTYPE_P(0);
	v2 = PG_GETARG_ARRAYTYPE_P(1);

	// postgres type of elements in an array
	element_type = ARR_ELEMTYPE(v1);

	// number of items in the arrays
	nitems1 = ARR_DIMS(v1)[0];
	nitems2 = ARR_DIMS(v2)[0];

//	if (nitems1 == 0 || nitems2 == 0 || nitems2 % nitems1 != 0)
//		abort();

        /* new array is the same as v1 for top 1 only !! */
	ndims = ARR_NDIM(v1);
	ndatabytes = ARR_SIZE(v1) - ARR_DATA_OFFSET(v1);
	dataoffset = 0;			/* marker for no null bitmap */
	nbytes = ndatabytes + ARR_OVERHEAD_NONULLS(ndims);

	result = (ArrayType *) palloc(nbytes);
	SET_VARSIZE(result, nbytes);
	result->ndim = ndims;
	result->dataoffset = dataoffset;
	result->elemtype = element_type;
        for(i=0;i<ndims;i++) {
          ARR_DIMS(result)[i]=ARR_DIMS(v1)[i];
          ARR_LBOUND(result)[i]=ARR_LBOUND(v1)[i];
        }

	// array v2 can either have nitems1 or nitems1*nitems1 or (nitems1+1)*nitems1 items, because of the -1 arrays from MR 
	// for the first and third case we want to skip the first nitems1 items 
	//int spos=0;
	spos = nitems2 % (nitems1*nitems1);
	for(i=0; i<nitems1; i++)
	  ((int*)ARR_DATA_PTR(result))[i] = 0; 

        // do sum over all possible value of y' calculation here
        for(i = spos; i < nitems2; i++) {
                  int k = (i-spos) / nitems1;
                  int k_rem = i % nitems1;

	     	  int new_score = ((int*)ARR_DATA_PTR(v1))[0*nitems1+k] + ((int*)ARR_DATA_PTR(v2))[i];
		// 0.5 is for rounding
	         ((int*)ARR_DATA_PTR(result))[0*nitems1+k_rem] = (int)(log(exp(((int*)ARR_DATA_PTR(result))[0*nitems1+k_rem]/1000.0) + exp(new_score/1000.0))*1000.0 + 0.5);
        }

	PG_RETURN_ARRAYTYPE_P(result);
}
Example #12
0
Datum
tsp_matrix(PG_FUNCTION_ARGS)
{
    FuncCallContext     *funcctx;
    int                  call_cntr;
    int                  max_calls;
    TupleDesc            tuple_desc;
    AttInMetadata       *attinmeta;

    DTYPE               *matrix;
    int                 *tsp_res;
    int                  num;

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

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

        matrix = get_pgarray(&num, PG_GETARG_ARRAYTYPE_P(0));

        ret = solve_tsp(matrix, num,
                        PG_GETARG_INT32(1), // start index
                        PG_GETARG_INT32(2), // end  index
                        &tsp_res);

        pfree(matrix);
        if (ret < 0) {
            elog(ERROR, "Error, failed to solve TSP.");
        }

        funcctx->max_calls = num;
        funcctx->user_fctx = tsp_res;

        /* Build a tuple descriptor for our result type */
        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);

        /*
         * generate attribute metadata needed later to produce tuples from raw
         * C strings
         */
        //attinmeta = TupleDescGetAttInMetadata(tuple_desc);
        //funcctx->attinmeta = attinmeta;

        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;
    tsp_res    = funcctx->user_fctx;

    DBG("Trying to allocate some memory");
    DBG("call_cntr = %i, max_calls = %i", call_cntr, max_calls);

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

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

        values[0] = Int32GetDatum(call_cntr);
        nulls[0] = ' ';
        values[1] = Int32GetDatum(tsp_res[call_cntr]);
        nulls[1] = ' ';

        DBG("RESULT: %d, %d", call_cntr, tsp_res[call_cntr]);

        DBG("Heap making");

        tuple = heap_formtuple(tuple_desc, values, nulls);

        DBG("Datum making");

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

        DBG("RESULT: seq:%d, id:%d", call_cntr, tsp_res[call_cntr]);
        DBG("Trying to free some memory");

        /* clean up (this is not really necessary) */
        pfree(values);
        pfree(nulls);


        SRF_RETURN_NEXT(funcctx, result);
    }
    else {   /* do when there is no more left */
        DBG("Freeing tsp_res");
        free(tsp_res);

        DBG("Ending function");
        SRF_RETURN_DONE(funcctx);
    }
}
Example #13
0
/*
 * SQL function jsonb_object(text[], text[])
 *
 * take separate name and value arrays of text to construct a jsonb object
 * pairwise.
 */
Datum
jsonb_object_two_arg(PG_FUNCTION_ARGS)
{
	ArrayType  *key_array = PG_GETARG_ARRAYTYPE_P(0);
	ArrayType  *val_array = PG_GETARG_ARRAYTYPE_P(1);
	int			nkdims = ARR_NDIM(key_array);
	int			nvdims = ARR_NDIM(val_array);
	Datum	   *key_datums,
			   *val_datums;
	bool	   *key_nulls,
			   *val_nulls;
	int			key_count,
				val_count,
				i;
	JsonbInState result;

	memset(&result, 0, sizeof(JsonbInState));

	(void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);

	if (nkdims > 1 || nkdims != nvdims)
		ereport(ERROR,
				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
				 errmsg("wrong number of array subscripts")));

	if (nkdims == 0)
		goto close_object;

	deconstruct_array(key_array,
					  TEXTOID, -1, false, 'i',
					  &key_datums, &key_nulls, &key_count);

	deconstruct_array(val_array,
					  TEXTOID, -1, false, 'i',
					  &val_datums, &val_nulls, &val_count);

	if (key_count != val_count)
		ereport(ERROR,
				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
				 errmsg("mismatched array dimensions")));

	for (i = 0; i < key_count; ++i)
	{
		JsonbValue	v;
		char	   *str;
		int			len;

		if (key_nulls[i])
			ereport(ERROR,
					(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
					 errmsg("null value not allowed for object key")));

		str = TextDatumGetCString(key_datums[i]);
		len = strlen(str);

		v.type = jbvString;

		v.val.string.len = len;
		v.val.string.val = str;

		(void) pushJsonbValue(&result.parseState, WJB_KEY, &v);

		if (val_nulls[i])
		{
			v.type = jbvNull;
		}
		else
		{
			str = TextDatumGetCString(val_datums[i]);
			len = strlen(str);

			v.type = jbvString;

			v.val.string.len = len;
			v.val.string.val = str;
		}

		(void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
	}

	pfree(key_datums);
	pfree(key_nulls);
	pfree(val_datums);
	pfree(val_nulls);

close_object:
	result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);

	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
}
Example #14
0
/*
 * SQL function jsonb_object(text[])
 *
 * take a one or two dimensional array of text as name value pairs
 * for a jsonb object.
 *
 */
Datum
jsonb_object(PG_FUNCTION_ARGS)
{
	ArrayType  *in_array = PG_GETARG_ARRAYTYPE_P(0);
	int			ndims = ARR_NDIM(in_array);
	Datum	   *in_datums;
	bool	   *in_nulls;
	int			in_count,
				count,
				i;
	JsonbInState result;

	memset(&result, 0, sizeof(JsonbInState));

	(void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);

	switch (ndims)
	{
		case 0:
			goto close_object;
			break;

		case 1:
			if ((ARR_DIMS(in_array)[0]) % 2)
				ereport(ERROR,
						(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
						 errmsg("array must have even number of elements")));
			break;

		case 2:
			if ((ARR_DIMS(in_array)[1]) != 2)
				ereport(ERROR,
						(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
						 errmsg("array must have two columns")));
			break;

		default:
			ereport(ERROR,
					(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
					 errmsg("wrong number of array subscripts")));
	}

	deconstruct_array(in_array,
					  TEXTOID, -1, false, 'i',
					  &in_datums, &in_nulls, &in_count);

	count = in_count / 2;

	for (i = 0; i < count; ++i)
	{
		JsonbValue	v;
		char	   *str;
		int			len;

		if (in_nulls[i * 2])
			ereport(ERROR,
					(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
					 errmsg("null value not allowed for object key")));

		str = TextDatumGetCString(in_datums[i * 2]);
		len = strlen(str);

		v.type = jbvString;

		v.val.string.len = len;
		v.val.string.val = str;

		(void) pushJsonbValue(&result.parseState, WJB_KEY, &v);

		if (in_nulls[i * 2 + 1])
		{
			v.type = jbvNull;
		}
		else
		{
			str = TextDatumGetCString(in_datums[i * 2 + 1]);
			len = strlen(str);

			v.type = jbvString;

			v.val.string.len = len;
			v.val.string.val = str;
		}

		(void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
	}

	pfree(in_datums);
	pfree(in_nulls);

close_object:
	result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);

	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
}
Example #15
0
Datum
hstore_from_array(PG_FUNCTION_ARGS)
{
	ArrayType  *in_array = PG_GETARG_ARRAYTYPE_P(0);
	int			ndims = ARR_NDIM(in_array);
	int			count;
	int4		buflen;
	HStore	   *out;
	Pairs	   *pairs;
	Datum	   *in_datums;
	bool	   *in_nulls;
	int			in_count;
	int			i;

	Assert(ARR_ELEMTYPE(in_array) == TEXTOID);

	switch (ndims)
	{
		case 0:
			out = hstorePairs(NULL, 0, 0);
			PG_RETURN_POINTER(out);

		case 1:
			if ((ARR_DIMS(in_array)[0]) % 2)
				ereport(ERROR,
						(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
						 errmsg("array must have even number of elements")));
			break;

		case 2:
			if ((ARR_DIMS(in_array)[1]) != 2)
				ereport(ERROR,
						(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
						 errmsg("array must have two columns")));
			break;

		default:
			ereport(ERROR,
					(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
					 errmsg("wrong number of array subscripts")));
	}

	deconstruct_array(in_array,
					  TEXTOID, -1, false, 'i',
					  &in_datums, &in_nulls, &in_count);

	count = in_count / 2;

	pairs = palloc(count * sizeof(Pairs));

	for (i = 0; i < count; ++i)
	{
		if (in_nulls[i * 2])
			ereport(ERROR,
					(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
					 errmsg("null value not allowed for hstore key")));

		if (in_nulls[i * 2 + 1])
		{
			pairs[i].key = VARDATA_ANY(in_datums[i * 2]);
			pairs[i].val = NULL;
			pairs[i].keylen = hstoreCheckKeyLen(VARSIZE_ANY_EXHDR(in_datums[i * 2]));
			pairs[i].vallen = 4;
			pairs[i].isnull = true;
			pairs[i].needfree = false;
		}
		else
		{
			pairs[i].key = VARDATA_ANY(in_datums[i * 2]);
			pairs[i].val = VARDATA_ANY(in_datums[i * 2 + 1]);
			pairs[i].keylen = hstoreCheckKeyLen(VARSIZE_ANY_EXHDR(in_datums[i * 2]));
			pairs[i].vallen = hstoreCheckValLen(VARSIZE_ANY_EXHDR(in_datums[i * 2 + 1]));
			pairs[i].isnull = false;
			pairs[i].needfree = false;
		}
	}

	count = hstoreUniquePairs(pairs, count, &buflen);

	out = hstorePairs(pairs, count, buflen);

	PG_RETURN_POINTER(out);
}
Example #16
0
Datum
hstore_delete_array(PG_FUNCTION_ARGS)
{
	HStore	   *hs = PG_GETARG_HS(0);
	HStore	   *out = palloc(VARSIZE(hs));
	int			hs_count = HS_COUNT(hs);
	char	   *ps,
			   *bufd,
			   *pd;
	HEntry	   *es,
			   *ed;
	int			i,
				j;
	int			outcount = 0;
	ArrayType  *key_array = PG_GETARG_ARRAYTYPE_P(1);
	int			nkeys;
	Pairs	   *key_pairs = hstoreArrayToPairs(key_array, &nkeys);

	SET_VARSIZE(out, VARSIZE(hs));
	HS_SETCOUNT(out, hs_count); /* temporary! */

	ps = STRPTR(hs);
	es = ARRPTR(hs);
	bufd = pd = STRPTR(out);
	ed = ARRPTR(out);

	if (nkeys == 0)
	{
		/* return a copy of the input, unchanged */
		memcpy(out, hs, VARSIZE(hs));
		HS_FIXSIZE(out, hs_count);
		HS_SETCOUNT(out, hs_count);
		PG_RETURN_POINTER(out);
	}

	/*
	 * this is in effect a merge between hs and key_pairs, both of which are
	 * already sorted by (keylen,key); we take keys from hs only
	 */

	for (i = j = 0; i < hs_count;)
	{
		int			difference;

		if (j >= nkeys)
			difference = -1;
		else
		{
			int			skeylen = HS_KEYLEN(es, i);

			if (skeylen == key_pairs[j].keylen)
				difference = strncmp(HS_KEY(es, ps, i),
									 key_pairs[j].key,
									 key_pairs[j].keylen);
			else
				difference = (skeylen > key_pairs[j].keylen) ? 1 : -1;
		}

		if (difference > 0)
			++j;
		else if (difference == 0)
			++i, ++j;
		else
		{
			HS_COPYITEM(ed, bufd, pd,
						HS_KEY(es, ps, i), HS_KEYLEN(es, i),
						HS_VALLEN(es, i), HS_VALISNULL(es, i));
			++outcount;
			++i;
		}
	}

	HS_FINALIZE(out, outcount, bufd, pd);

	PG_RETURN_POINTER(out);
}
Example #17
0
Datum
gin_extract_jsonb_query(PG_FUNCTION_ARGS)
{
	int32	   *nentries = (int32 *) PG_GETARG_POINTER(1);
	StrategyNumber strategy = PG_GETARG_UINT16(2);
	int32	   *searchMode = (int32 *) PG_GETARG_POINTER(6);
	Datum	   *entries;

	if (strategy == JsonbContainsStrategyNumber)
	{
		/* Query is a jsonb, so just apply gin_extract_jsonb... */
		entries = (Datum *)
			DatumGetPointer(DirectFunctionCall2(gin_extract_jsonb,
												PG_GETARG_DATUM(0),
												PointerGetDatum(nentries)));
		/* ...although "contains {}" requires a full index scan */
		if (*nentries == 0)
			*searchMode = GIN_SEARCH_MODE_ALL;
	}
	else if (strategy == JsonbExistsStrategyNumber)
	{
		/* Query is a text string, which we treat as a key */
		text	   *query = PG_GETARG_TEXT_PP(0);

		*nentries = 1;
		entries = (Datum *) palloc(sizeof(Datum));
		entries[0] = make_text_key(JGINFLAG_KEY,
								   VARDATA_ANY(query),
								   VARSIZE_ANY_EXHDR(query));
	}
	else if (strategy == JsonbExistsAnyStrategyNumber ||
			 strategy == JsonbExistsAllStrategyNumber)
	{
		/* Query is a text array; each element is treated as a key */
		ArrayType  *query = PG_GETARG_ARRAYTYPE_P(0);
		Datum	   *key_datums;
		bool	   *key_nulls;
		int			key_count;
		int			i,
					j;

		deconstruct_array(query,
						  TEXTOID, -1, false, 'i',
						  &key_datums, &key_nulls, &key_count);

		entries = (Datum *) palloc(sizeof(Datum) * key_count);

		for (i = 0, j = 0; i < key_count; i++)
		{
			/* Nulls in the array are ignored */
			if (key_nulls[i])
				continue;
			entries[j++] = make_text_key(JGINFLAG_KEY,
										 VARDATA_ANY(key_datums[i]),
										 VARSIZE_ANY_EXHDR(key_datums[i]));
		}

		*nentries = j;
		/* ExistsAll with no keys should match everything */
		if (j == 0 && strategy == JsonbExistsAllStrategyNumber)
			*searchMode = GIN_SEARCH_MODE_ALL;
	}
	else
	{
		elog(ERROR, "unrecognized strategy number: %d", strategy);
		entries = NULL;			/* keep compiler quiet */
	}

	PG_RETURN_POINTER(entries);
}
Example #18
0
/*
 * nb_classify_accum - Naive Bayesian Classification Accumulator
 */
Datum 
nb_classify_accum(PG_FUNCTION_ARGS)
{
	nb_classify_state  state;
	TupleDesc          resultDesc;
	int                i;
	int                nclasses;
	ArrayType         *classes;          /* arg[1] */
	int64              attr_count;       /* arg[2] */
	ArrayType         *class_count;      /* arg[3] */
	ArrayType         *class_total;      /* arg[4] */
	HeapTuple          result;
	Datum              resultDatum[3];
	bool               resultNull[3];
	bool               skip;
	int64             *class_data;
	int64             *total_data;
	float8            *prior_data;
	int64             *stotal_data;

	/* Check input parameters */
	if (PG_NARGS() != 5)
	{
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("nb_classify_accum called with %d arguments", 
						PG_NARGS())));
	}

	/* Skip rows with NULLs */
	if (PG_ARGISNULL(1) || PG_ARGISNULL(3) || PG_ARGISNULL(4))
	{
		if (PG_ARGISNULL(0))
			PG_RETURN_NULL();
		PG_RETURN_DATUM(PG_GETARG_DATUM(0));
	}
	classes     = PG_GETARG_ARRAYTYPE_P(1);
	attr_count  = PG_ARGISNULL(2) ? 0 : PG_GETARG_INT64(2);
	class_count = PG_GETARG_ARRAYTYPE_P(3);
	class_total = PG_GETARG_ARRAYTYPE_P(4);

	if (ARR_NDIM(classes) != 1 || 
		ARR_NDIM(class_count) != 1 || 
		ARR_NDIM(class_total) != 1)
	{
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("nb_classify cannot accumulate multidimensional arrays")));
	}

	/* All three arrays must be equal cardinality */
	nclasses = ARR_DIMS(classes)[0];
	if (ARR_DIMS(class_count)[0] != nclasses ||
		ARR_DIMS(class_total)[0] != nclasses)
	{
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("nb_classify: non-conformable arrays")));
	}
	
	class_data = (int64*) ARR_DATA_PTR(class_count);
	total_data = (int64*) ARR_DATA_PTR(class_total);

	/* It is an error for class_data, total_data, or attr_count to be a 
	   negative number */
	if (attr_count < 0) 
	{
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("nb_classify: attr_count value must be >= 0")));

	}
	skip = false;
	for (i = 0; i < nclasses; i++) 
	{
		if (class_data[i] < 0) 
		{
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
					 errmsg("nb_classify: class_data values must be >= 0")));
		}
		if (total_data[i] < 0) 
		{
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
					 errmsg("nb_classify: total_data values must be >= 0")));
		}
		if (class_data[i] > total_data[i]) 
		{
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
					 errmsg("nb_classify: class_data values must be <= total_data")));
		}

		/* 
		 * If we do not have an adjustment value and any class has a zero value
		 * then we must skip this row, otherwise we will try to calculate ln(0)
		 */
		if (attr_count == 0 && class_data[i] == 0) 
		{
			skip = true;
		}
	}
	if (skip)
	{
		PG_RETURN_DATUM(PG_GETARG_DATUM(0));			
	}



	/* Get/create the accumulation state */
	if (!PG_ARGISNULL(0))
	{
		HeapTupleHeader tup;
		tup = (fcinfo->context && IsA(fcinfo->context, AggState))
			? PG_GETARG_HEAPTUPLEHEADER(0)
			: PG_GETARG_HEAPTUPLEHEADER_COPY(0);

		get_nb_state(tup, &state, nclasses);
	}
	else
	{
		/* Construct the state arrays */
		int     size;

		/* allocate memory and copy the classes array */
		size = VARSIZE(classes);
		state.classes = (ArrayType *) palloc(size);
		SET_VARSIZE(state.classes, size);
		memcpy(state.classes, classes, size);

		/* allocate memory and construct the accumulator array */
		size = ARR_OVERHEAD_NONULLS(1) + nclasses * sizeof(float8);
		state.accum = (ArrayType *) palloc(size);
		SET_VARSIZE(state.accum, size);
		state.accum->ndim          = 1;
		state.accum->dataoffset    = 0;
		ARR_ELEMTYPE(state.accum)  = FLOAT8OID;
		ARR_DIMS(state.accum)[0]   = nclasses;
		ARR_LBOUND(state.accum)[0] = 1;
		prior_data = (float8*) ARR_DATA_PTR(state.accum);
		for (i = 0; i < nclasses; i++)
			prior_data[i] = 0;

		/* allocate memory and construct the total array */
		size = ARR_OVERHEAD_NONULLS(1) + nclasses * sizeof(int64);
		state.total = (ArrayType *) palloc(size);
		SET_VARSIZE(state.total, size);
		state.total->ndim          = 1;
		state.total->dataoffset    = 0;
		ARR_ELEMTYPE(state.total)  = INT8OID;
		ARR_DIMS(state.total)[0]   = nclasses;
		ARR_LBOUND(state.total)[0] = 1;
		stotal_data = (int64*) ARR_DATA_PTR(state.total);
		for (i = 0; i < nclasses; i++)
			stotal_data[i] = 0;
	}

	/* Adjust the prior based on the current input row */
	prior_data = (float8*) ARR_DATA_PTR(state.accum);
	stotal_data = (int64*) ARR_DATA_PTR(state.total);
	for (i = 0; i < nclasses; i++)
	{
		/*
		 * Calculate the accumulation value for the classifier
		 *
		 * The logical calculation is: 
		 *     product((class[i]+1)/(total_data[i]+attr_count))
		 *
		 * Instead of this calculation we calculate:
		 *     sum(ln((class[i]+1)/(total_data[i]+attr_count)))
		 *
		 * The reason for this is to increase the numerical stability of
		 * the algorithm.
		 *
		 * Since the ln(0) is undefined we want to increment the count 
		 * for all classes. 
		 *
		 * This get's a bit more complicated for the denominator which
		 * needs to know how many values there are for this attribute
		 * so that we keep the total probability for the attribute = 1.
		 * To handle this the aggregation function should be passed the
		 * number of distinct values for the aggregate it is computing.
		 *
		 * If for some reason this value is not present, or < 1 then we
		 * just switch to non-adjusted calculations.  In this case we 
		 * will simply skip over any row that has a 0 count on any 
		 * class_data index. (handled above)
		 */
		if (attr_count > 1)
			prior_data[i] += log((class_data[i]+1)/(float8)(total_data[i] + attr_count));
		else
			prior_data[i] += log(class_data[i]/(float8)total_data[i]);

		/* 
		 * The total array should be constant throughout, but if not it should
		 * reflect the maximum values encountered 
		 */
		if (total_data[i] > stotal_data[i])
			stotal_data[i] = total_data[i];
	}


	/* Construct the return tuple */
	if (get_call_result_type(fcinfo, NULL, &resultDesc) != TYPEFUNC_COMPOSITE)
		elog(ERROR, "return type must be a row type");
	BlessTupleDesc(resultDesc); 
	
	resultDatum[0] = PointerGetDatum(state.classes);
	resultDatum[1] = PointerGetDatum(state.accum);
	resultDatum[2] = PointerGetDatum(state.total);
	resultNull[0]  = false;
	resultNull[1]  = false;
	resultNull[2]  = false;

	result = heap_form_tuple(resultDesc, resultDatum, resultNull);
	PG_RETURN_DATUM(HeapTupleGetDatum(result));
}
Example #19
0
Datum
argmin(PG_FUNCTION_ARGS)
{
	int i=0; // iteration
	int min_i = 0; // marker
	// just use a double
	double s = 0; // marked value

	// Unwrap
	ArrayType *anyArray = PG_GETARG_ARRAYTYPE_P(0);
	Oid oid = ARR_ELEMTYPE(anyArray);

	// there is clearly a better way to do the below 
	// in a general way, but that will have to wait
	// I need should be able to iterate with typelen
	//	int16 typlen;
	//	bool typbyval;
	//	char typalign;
	//    get_typlenbyvalalign(oid,&typlen,&typbyval, &typalign);
	//    Datum el = array_ref(anyArray, ARR_NDIM(anyArray), i, -1, typlen, typbyval, typalign, &isNull );	

	if(oid == INT2OID)
	{
		int16 *a = (int16 *)  ARR_DATA_PTR(anyArray);
		s = a[i];
		// move through it
		for(++i; i< ARR_DIMS(anyArray)[0]; ++i)
		{
			if (a[i] < s)
			{
				s = a[i];
				min_i = i;
			}
		}
	}
	else if (oid == INT4OID)
	{
		int32 *a = (int32 *)  ARR_DATA_PTR(anyArray);
		s = a[i];
		// move through it
		for(++i; i< ARR_DIMS(anyArray)[0]; ++i)
		{
			if (a[i] < s)
			{
				s = a[i];
				min_i = i;
			}
		}
	}
	else if (oid == INT8OID)
	{
		int64 *a = (int64 *)  ARR_DATA_PTR(anyArray);
		s = a[i];
		// move through it
		for(++i; i< ARR_DIMS(anyArray)[0]; ++i)
		{
			if (a[i] < s)
			{
				s = a[i];
				min_i = i;
			}
		}
	}
	else if (oid == FLOAT4OID)
	{
		float4 *a = (float4 *)  ARR_DATA_PTR(anyArray);
		s = a[i];
		// move through it
		for(++i; i< ARR_DIMS(anyArray)[0]; ++i)
		{
			if (a[i] < s)
			{
				s = a[i];
				min_i = i;
			}
		}
	}
	else if (oid == FLOAT8OID)
	{
		float8 *a = (float8 *)  ARR_DATA_PTR(anyArray);
		s = a[i];
		// move through it
		for(++i; i< ARR_DIMS(anyArray)[0]; ++i)
		{
			if (a[i] < s)
			{
				s = a[i];
				min_i = i;
			}
		}
	}
	else if(oid == NUMERICOID)
	{
		ereport(INFO, (errmsg_internal("Numeric[] not implemented: %d", oid)));

	}
	else
	{
		ereport(INFO, (errmsg_internal("wrong types: %d", oid)));
	}

		
	PG_RETURN_INT32( min_i + 1 );
}
Example #20
0
Datum
gin_extract_hstore_query(PG_FUNCTION_ARGS)
{
	int32	   *nentries = (int32 *) PG_GETARG_POINTER(1);
	StrategyNumber strategy = PG_GETARG_UINT16(2);
	int32	   *searchMode = (int32 *) PG_GETARG_POINTER(6);
	Datum	   *entries;

	if (strategy == HStoreContainsStrategyNumber)
	{
		/* Query is an hstore, so just apply gin_extract_hstore... */
		entries = (Datum *)
			DatumGetPointer(DirectFunctionCall2(gin_extract_hstore,
												PG_GETARG_DATUM(0),
												PointerGetDatum(nentries)));
		/* ... except that "contains {}" requires a full index scan */
		if (entries == NULL)
			*searchMode = GIN_SEARCH_MODE_ALL;
	}
	else if (strategy == HStoreExistsStrategyNumber)
	{
		text	   *query = PG_GETARG_TEXT_PP(0);
		text	   *item;

		*nentries = 1;
		entries = (Datum *) palloc(sizeof(Datum));
		item = makeitem(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query), KEYFLAG);
		entries[0] = PointerGetDatum(item);
	}
	else if (strategy == HStoreExistsAnyStrategyNumber ||
			 strategy == HStoreExistsAllStrategyNumber)
	{
		ArrayType  *query = PG_GETARG_ARRAYTYPE_P(0);
		Datum	   *key_datums;
		bool	   *key_nulls;
		int			key_count;
		int			i,
					j;
		text	   *item;

		deconstruct_array(query,
						  TEXTOID, -1, false, 'i',
						  &key_datums, &key_nulls, &key_count);

		entries = (Datum *) palloc(sizeof(Datum) * key_count);

		for (i = 0, j = 0; i < key_count; ++i)
		{
			/* Nulls in the array are ignored, cf hstoreArrayToPairs */
			if (key_nulls[i])
				continue;
			item = makeitem(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ, KEYFLAG);
			entries[j++] = PointerGetDatum(item);
		}

		*nentries = j;
		/* ExistsAll with no keys should match everything */
		if (j == 0 && strategy == HStoreExistsAllStrategyNumber)
			*searchMode = GIN_SEARCH_MODE_ALL;
	}
	else
	{
		elog(ERROR, "unrecognized strategy number: %d", strategy);
		entries = NULL;			/* keep compiler quiet */
	}

	PG_RETURN_POINTER(entries);
}
Example #21
0
Datum 
text_unpivot(PG_FUNCTION_ARGS)
{
	FuncCallContext      *funcctx;
	unpivot_fctx         *fctx;
	MemoryContext         oldcontext;
	Datum                 d[2];
	bool                  isna[2];

	/* stuff done only on the first call of the function */
	if (SRF_IS_FIRSTCALL())
	{
		TupleDesc  tupdesc;
		ArrayType *labels;
		ArrayType *data;
		Oid        eltype1;
		Oid        eltype2;

		/* see if we were given an explicit step size */
		if (PG_NARGS() != 2)
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
					 errmsg("number of parameters != 2")));

		/* 
		 * Type check inputs:
		 *    0: label text[]
		 *    1: value anyarray
		 */
		eltype1 = get_fn_expr_argtype(fcinfo->flinfo, 0);
		eltype2 = get_fn_expr_argtype(fcinfo->flinfo, 1);

		if (!OidIsValid(eltype1))
			elog(ERROR, "could not determine data type of input 'label'");
		if (!OidIsValid(eltype2))
			elog(ERROR, "could not determine data type of input 'value'");

		/* Strict function, return null on null input */
		if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
			PG_RETURN_NULL();
		
		/* 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);

        /* Build a tuple descriptor for our result type */
        if (get_call_result_type(fcinfo, NULL, &tupdesc) != 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(tupdesc);

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

		/* Use fctx to keep state from call to call */
		labels = PG_GETARG_ARRAYTYPE_P(0);
		data   = PG_GETARG_ARRAYTYPE_P(1);
		array_loop(labels, ARR_LBOUND(labels)[0], &fctx->label_iter);
		array_loop(data,   ARR_LBOUND(labels)[0], &fctx->data_iter);		

		funcctx->user_fctx = fctx;
		MemoryContextSwitchTo(oldcontext);
	}

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

	/* get the saved state and use current as the result for this iteration */
	fctx = (unpivot_fctx*) funcctx->user_fctx;

	if (array_next(&fctx->label_iter, &d[0], &isna[0]))
	{
		HeapTuple tuple;

		array_next(&fctx->data_iter, &d[1], &isna[1]);
		tuple = heap_form_tuple(funcctx->tuple_desc, d, isna);
		SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));		
	}
	else
	{
		SRF_RETURN_DONE(funcctx);
	}
}
Example #22
0
PGDLLEXPORT Datum MY_FUNCTION_NAME(PG_FUNCTION_ARGS) {
    FuncCallContext     *funcctx;
    TupleDesc           tuple_desc;

    /**************************************************************************/
    /*                          MODIFY AS NEEDED                              */
    /*                                                                        */
    MY_RETURN_VALUE_TYPE  *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                          */
        /*
           MY_QUERY_LINE1
         **********************************************************************/


        PGR_DBG("Calling process");
        process(
                text_to_cstring(PG_GETARG_TEXT_P(0)),
                PG_GETARG_INT64(1),
                PG_GETARG_INT64(2),
#if 0
                /*
                 *  handling arrays example
                 */

                PG_GETARG_ARRAYTYPE_P(1),
                PG_GETARG_ARRAYTYPE_P(2),
#endif
                PG_GETARG_BOOL(3),
                PG_GETARG_BOOL(4),
                &result_tuples,
                &result_count);


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

#if PGSQL_VERSION > 94
        funcctx->max_calls = result_count;
#else
        funcctx->max_calls = (uint32_t)result_count;
#endif
        funcctx->user_fctx = result_tuples;
        if (get_call_result_type(fcinfo, NULL, &tuple_desc)
                != TYPEFUNC_COMPOSITE) {
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     errmsg("function returning record called in context "
                         "that cannot accept type record")));
        }

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

    funcctx = SRF_PERCALL_SETUP();
    tuple_desc = funcctx->tuple_desc;
    result_tuples = (MY_RETURN_VALUE_TYPE*) funcctx->user_fctx;

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

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

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


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

        // postgres starts counting from 1
        values[0] = Int32GetDatum(funcctx->call_cntr + 1);
        values[1] = Int32GetDatum(result_tuples[funcctx->call_cntr].seq);
        values[2] = Int64GetDatum(result_tuples[funcctx->call_cntr].node);
        values[3] = Int64GetDatum(result_tuples[funcctx->call_cntr].edge);
        values[4] = Float8GetDatum(result_tuples[funcctx->call_cntr].cost);
        values[5] = Float8GetDatum(result_tuples[funcctx->call_cntr].agg_cost);
        /**********************************************************************/

        tuple = heap_form_tuple(tuple_desc, values, nulls);
        result = HeapTupleGetDatum(tuple);
        SRF_RETURN_NEXT(funcctx, result);
    } else {
        /**********************************************************************/
        /*                          MODIFY AS NEEDED                          */

        PGR_DBG("Clean up code");

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

        SRF_RETURN_DONE(funcctx);
    }
}
Example #23
0
Datum
#else  // _MSC_VER
PGDLLEXPORT Datum
#endif
many_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 anyarray,
        // end_vid BIGINT,
        // directed BOOLEAN default true,

        PGR_DBG("Initializing arrays");
        int64_t* start_vidsArr;
        size_t size_start_vidsArr;
        start_vidsArr = (int64_t*)
            pgr_get_bigIntArray(&size_start_vidsArr, PG_GETARG_ARRAYTYPE_P(1));
        PGR_DBG("start_vidsArr size %ld ", size_start_vidsArr);

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

        PGR_DBG("Cleaning arrays");
        free(start_vidsArr);
        /*                                                                   */
        /*********************************************************************/

        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 start_vid BIGINT,
        // OUT end_vid BIGINT,
        // 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(call_cntr + 1);
        values[1] = Int32GetDatum(result_tuples[call_cntr].seq);
        values[2] = Int64GetDatum(result_tuples[call_cntr].start_id);
        values[3] = Int64GetDatum(result_tuples[call_cntr].node);
        values[4] = Int64GetDatum(result_tuples[call_cntr].edge);
        values[5] = Float8GetDatum(result_tuples[call_cntr].cost);
        values[6] = 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);
    }
}
Example #24
0
Datum
alpine_miner_nn_ca_o(PG_FUNCTION_ARGS)
{

	ArrayType  *weight_arg, *columns_arg, *input_range_arg, *input_base_arg,*hidden_node_number_arg, *result;
    Datum     *weight_data, *columns_data, *input_range_data, *input_base_data, *hidden_node_number_data, *result_data;
    bool       *weight_nulls, *columns_nulls, *input_range_nulls, *input_base_nulls, *hidden_node_number_nulls,*result_nulls;
	int         weight_count, columns_count, input_range_count, input_base_count, hidden_node_number_count,result_count ;
    Oid         result_eltype;
	int16 result_typlen;
	bool result_typbyval;
	char result_typalign;

	double output_range_arg,output_base_arg;
	int hidden_layer_number_arg, output_node_no_arg;
	bool normalize_arg, numerical_label_arg ;
        int         ndims, *dims, *lbs;

	int i;
	int j;
	int k;

	int all_hidden_node_count;

	int weight_index;
	int hidden_node_number_index = 0;

	bool null_data;
	double * input;
	double * output;
	int * hidden_node_number;
	double *weight;
	double *hidden_node_output;
	if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3) || PG_ARGISNULL(4) || PG_ARGISNULL(5) || PG_ARGISNULL(6) || PG_ARGISNULL(7) || PG_ARGISNULL(8) || PG_ARGISNULL(9) || PG_ARGISNULL(10))
	{
		PG_RETURN_NULL();
	}

        /* get weight_arg args */
        weight_arg = PG_GETARG_ARRAYTYPE_P(0);

	null_data = alpine_miner_deconstruct_array(weight_arg, &weight_data, &weight_nulls,&weight_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

        columns_arg = PG_GETARG_ARRAYTYPE_P(1);
	null_data = alpine_miner_deconstruct_array(columns_arg, &columns_data, &columns_nulls,&columns_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

    /* get input_range_arg args */
    input_range_arg = PG_GETARG_ARRAYTYPE_P(2);
	null_data = alpine_miner_deconstruct_array(input_range_arg, &input_range_data, &input_range_nulls,&input_range_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

    /* get input_base_arg args */
    input_base_arg = PG_GETARG_ARRAYTYPE_P(3);
	null_data = alpine_miner_deconstruct_array(input_base_arg, &input_base_data, &input_base_nulls,&input_base_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

    /* get hidden_node_number_arg args */
    hidden_node_number_arg = PG_GETARG_ARRAYTYPE_P(4);
	null_data = alpine_miner_deconstruct_array(hidden_node_number_arg, &hidden_node_number_data, &hidden_node_number_nulls,&hidden_node_number_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

	hidden_layer_number_arg= PG_GETARG_INT32(5);

	output_range_arg = PG_GETARG_FLOAT8(6);
	output_base_arg = PG_GETARG_FLOAT8(7);
	output_node_no_arg  = PG_GETARG_INT32(8);
	normalize_arg = PG_GETARG_BOOL(9); 
	numerical_label_arg = PG_GETARG_BOOL(10); 

#ifdef ALPINE_DEBUG 
	elog(WARNING,"%f",DatumGetFloat8(columns_data[0]));
#endif
	input =  (double*)palloc(columns_count * sizeof(double));;




	output = (double*)palloc(output_node_no_arg * sizeof(double));
	hidden_node_number = (int*) palloc(hidden_node_number_count * sizeof(int));


	weight = (double*)palloc(weight_count * sizeof(double));
	for (i = 0; i < weight_count; i++)
	{
		weight[i] = DatumGetFloat8(weight_data[i]);
	}
	all_hidden_node_count = 0;
	for (i = 0; i < hidden_layer_number_arg; i++)
	{
		hidden_node_number[i] = DatumGetInt32(hidden_node_number_data[i]);
		all_hidden_node_count += hidden_node_number[i];
	}

	hidden_node_output = (double*)palloc(all_hidden_node_count * sizeof(double));


        /* get output array element type */
	result_eltype = FLOAT8OID;
        get_typlenbyvalalign(result_eltype, &result_typlen, &result_typbyval, &result_typalign);

        /* construct result array */
	result_count = output_node_no_arg;
        result_data = (Datum *)palloc(result_count * sizeof(Datum));
        result_nulls = (bool *)palloc(result_count * sizeof(bool));
	for (i = 0; i < result_count; i++)
	{
		result_nulls[i] = false;
	}

	//caculate input 
        if (normalize_arg) 
        {
            i = 0;
            while (i < columns_count)
            {
                if (DatumGetFloat8(input_range_data[i]) != 0)
                {
                   input[i] = ((DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i]))/DatumGetFloat8(input_range_data[i]));
		}
                else
		{
                   input[i] = (DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i]));
                }
#ifdef ALPINE_DEBUG 
		elog(WARNING, "input:%f", input[i]);
#endif
		i = i + 1;
            }
	}
        else
	{
		i = 0;
        	while (i < columns_count)
		{
               	    input[i] = DatumGetFloat8(columns_data[i]);
               	    i = i + 1;
        	}
	}

	// caculate hidden node output of 1st layer 
        i = 0;
        while (i < hidden_node_number[0])
	{
                hidden_node_output[i] = weight[0+i*(columns_count + 1)];
                j = 0;
                while (j < columns_count)
		{
                        hidden_node_output[i] = hidden_node_output[i]+input[j]*weight[1 + j  + i *(columns_count + 1)];
#ifdef ALPINE_DEBUG 
			elog(WARNING,"hiddensum[%d] input[%d] %f weight[%d] %f", i, j,input[j] , 1+j  +(i)*(columns_count +1), weight[1+j +i*(columns_count + 1)]);
#endif
                        j = j + 1;
		}

		if (hidden_node_output[i] < -45.0)
		{
			hidden_node_output[i] = 0;
		}
		else if (hidden_node_output[i] > 45.0)
		{
			hidden_node_output[i] = 1;
		}
		else
		{
            	    hidden_node_output[i] = (1.0/(1.0+exp( -1.0 * hidden_node_output[i])));
		}
#ifdef ALPINE_DEBUG 
		 elog(WARNING,"hidden[%d] %f", i, hidden_node_output[i]);
#endif
                i = i + 1;
	}
//       calculate hidden layer 2~last output
        weight_index = hidden_node_number[0] * (columns_count + 1) ;

        if (hidden_layer_number_arg > 1)
	{
	        hidden_node_number_index = 0;
	        i = 1;
	        while (i < hidden_layer_number_arg )
		{
	                hidden_node_number_index = hidden_node_number_index + hidden_node_number[i - 1];
	                j = 0;
	                while (j < hidden_node_number[i]) 
			{
	                        hidden_node_output[hidden_node_number_index + j] = weight[weight_index + (hidden_node_number[i - 1] +1) * j];
	                        k = 0;
	                        while (k < hidden_node_number[i - 1])
				{ 
	                                hidden_node_output[hidden_node_number_index + j] = hidden_node_output[hidden_node_number_index + j]+hidden_node_output[hidden_node_number_index - hidden_node_number[i - 1] + k]*weight[weight_index + (hidden_node_number[i - 1] +1) * j + k + 1];
	                                k = k + 1;
				}
				if (hidden_node_output[hidden_node_number_index + j] < -45.0)
				{
					hidden_node_output[hidden_node_number_index + j] = 0;
				}
				else if (hidden_node_output[hidden_node_number_index + j] > 45.0)
				{
					hidden_node_output[hidden_node_number_index + j] = 1;
				}
				else
				{
	                        	hidden_node_output[hidden_node_number_index + j] = (1.0/(1+exp(-1.0*hidden_node_output[hidden_node_number_index+j])));
				}
	                        j = j + 1;
	                }
	                weight_index = weight_index + hidden_node_number[i] * (hidden_node_number[i - 1] + 1);
	                i = i + 1;
	       }
        }

	//compute output value of  output node;
        i = 0;
        while (i < output_node_no_arg)
	{
                output[i] = weight[weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i];
#ifdef ALPINE_DEBUG 
		elog(WARNING,"weightindex:%d,weight[%d] %f",weight_index, weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i, output[i]);
#endif
                j = 0;
                while (j < hidden_node_number[hidden_layer_number_arg-1])
		{
#ifdef ALPINE_DEBUG 
			elog(WARNING,"ouput[%d]:%f ,hidden_node_number_index:%d,j:%d, weight[%d]:%f",i,output[i], hidden_node_number_index ,j,1+j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i , weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ]);
#endif
                        output[i] = output[i]+hidden_node_output[hidden_node_number_index + j]
					* weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ];
                        j = j + 1;
                }
#ifdef ALPINE_DEBUG 
		 elog(WARNING,"ouputsum[%d] %f", i, output[i]);
#endif
		if (numerical_label_arg)
		{
                	output[i] = ((output[i]) * output_range_arg+output_base_arg);
#ifdef ALPINE_DEBUG 
			elog(WARNING,"output:%f, %f,%f",output[i],output_range_arg,output_base_arg);
#endif
		}
		else
		{
			if (output[i] < -45.0)
			{
				output[i] = 0;
			}
			else if (output[i] > 45.0)
			{
				output[i] = 1;
			}
			else
			{
				output[i] = (1.0/(1+exp(-1.0*output[i])));
			}
		}
#ifdef ALPINE_DEBUG 
		 elog(WARNING,"ouputsum2[%d] %f", i, output[i]);
#endif
                i = i + 1;
	}



	ndims = 1;
	dims = (int *) palloc(sizeof(int));
	dims[0] = result_count;
	lbs = (int *) palloc(sizeof(int));
	lbs[0] = 1;
	for (i = 0; i < output_node_no_arg; i++)
	{
		result_data[i] = Float8GetDatum(output[i]);
#ifdef ALPINE_DEBUG 
		elog(WARNING,"output[%d]:%f",i, output[i]);
#endif
	}

	result = construct_md_array((void *)result_data, result_nulls, ndims, dims,
			lbs, result_eltype, result_typlen, result_typbyval, result_typalign);

//	pfree(result);
	pfree(weight_data);
	pfree(columns_data);
	pfree(input_range_data);
	pfree(input_base_data);
	pfree(hidden_node_number_data);
	pfree(result_data);
	pfree(weight_nulls);
	pfree(columns_nulls);
	pfree(input_range_nulls);
	pfree(input_base_nulls);
	pfree(hidden_node_number_nulls);
	pfree(result_nulls);
	pfree(input);
	pfree(output);
	pfree(lbs);
	pfree(dims);
	pfree(hidden_node_output);
	pfree(weight);
	pfree(hidden_node_number);

        PG_RETURN_ARRAYTYPE_P(result);
}
/*-----------------------------------------------------------------------------
 * array_cat :
 *		concatenate two nD arrays to form an nD array, or
 *		push an (n-1)D array onto the end of an nD array
 *----------------------------------------------------------------------------
 */
Datum
array_cat(PG_FUNCTION_ARGS)
{
	ArrayType  *v1,
			   *v2;
	ArrayType  *result;
	int		   *dims,
			   *lbs,
				ndims,
				nitems,
				ndatabytes,
				nbytes;
	int		   *dims1,
			   *lbs1,
				ndims1,
				nitems1,
				ndatabytes1;
	int		   *dims2,
			   *lbs2,
				ndims2,
				nitems2,
				ndatabytes2;
	int			i;
	char	   *dat1,
			   *dat2;
	bits8	   *bitmap1,
			   *bitmap2;
	Oid			element_type;
	Oid			element_type1;
	Oid			element_type2;
	int32		dataoffset;

	/* Concatenating a null array is a no-op, just return the other input */
	if (PG_ARGISNULL(0))
	{
		if (PG_ARGISNULL(1))
			PG_RETURN_NULL();
		result = PG_GETARG_ARRAYTYPE_P(1);
		PG_RETURN_ARRAYTYPE_P(result);
	}
	if (PG_ARGISNULL(1))
	{
		result = PG_GETARG_ARRAYTYPE_P(0);
		PG_RETURN_ARRAYTYPE_P(result);
	}

	v1 = PG_GETARG_ARRAYTYPE_P(0);
	v2 = PG_GETARG_ARRAYTYPE_P(1);

	element_type1 = ARR_ELEMTYPE(v1);
	element_type2 = ARR_ELEMTYPE(v2);

	/* Check we have matching element types */
	if (element_type1 != element_type2)
		ereport(ERROR,
				(errcode(ERRCODE_DATATYPE_MISMATCH),
				 errmsg("cannot concatenate incompatible arrays"),
				 errdetail("Arrays with element types %s and %s are not "
						   "compatible for concatenation.",
						   format_type_be(element_type1),
						   format_type_be(element_type2))));

	/* OK, use it */
	element_type = element_type1;

	/*----------
	 * We must have one of the following combinations of inputs:
	 * 1) one empty array, and one non-empty array
	 * 2) both arrays empty
	 * 3) two arrays with ndims1 == ndims2
	 * 4) ndims1 == ndims2 - 1
	 * 5) ndims1 == ndims2 + 1
	 *----------
	 */
	ndims1 = ARR_NDIM(v1);
	ndims2 = ARR_NDIM(v2);

	/*
	 * short circuit - if one input array is empty, and the other is not, we
	 * return the non-empty one as the result
	 *
	 * if both are empty, return the first one
	 */
	if (ndims1 == 0 && ndims2 > 0)
		PG_RETURN_ARRAYTYPE_P(v2);

	if (ndims2 == 0)
		PG_RETURN_ARRAYTYPE_P(v1);

	/* the rest fall under rule 3, 4, or 5 */
	if (ndims1 != ndims2 &&
		ndims1 != ndims2 - 1 &&
		ndims1 != ndims2 + 1)
		ereport(ERROR,
				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
				 errmsg("cannot concatenate incompatible arrays"),
				 errdetail("Arrays of %d and %d dimensions are not "
						   "compatible for concatenation.",
						   ndims1, ndims2)));

	/* get argument array details */
	lbs1 = ARR_LBOUND(v1);
	lbs2 = ARR_LBOUND(v2);
	dims1 = ARR_DIMS(v1);
	dims2 = ARR_DIMS(v2);
	dat1 = ARR_DATA_PTR(v1);
	dat2 = ARR_DATA_PTR(v2);
	bitmap1 = ARR_NULLBITMAP(v1);
	bitmap2 = ARR_NULLBITMAP(v2);
	nitems1 = ArrayGetNItems(ndims1, dims1);
	nitems2 = ArrayGetNItems(ndims2, dims2);
	ndatabytes1 = ARR_SIZE(v1) - ARR_DATA_OFFSET(v1);
	ndatabytes2 = ARR_SIZE(v2) - ARR_DATA_OFFSET(v2);

	if (ndims1 == ndims2)
	{
		/*
		 * resulting array is made up of the elements (possibly arrays
		 * themselves) of the input argument arrays
		 */
		ndims = ndims1;
		dims = (int *) palloc(ndims * sizeof(int));
		lbs = (int *) palloc(ndims * sizeof(int));

		dims[0] = dims1[0] + dims2[0];
		lbs[0] = lbs1[0];

		for (i = 1; i < ndims; i++)
		{
			if (dims1[i] != dims2[i] || lbs1[i] != lbs2[i])
				ereport(ERROR,
						(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
						 errmsg("cannot concatenate incompatible arrays"),
					errdetail("Arrays with differing element dimensions are "
							  "not compatible for concatenation.")));

			dims[i] = dims1[i];
			lbs[i] = lbs1[i];
		}
	}
	else if (ndims1 == ndims2 - 1)
	{
		/*
		 * resulting array has the second argument as the outer array, with
		 * the first argument inserted at the front of the outer dimension
		 */
		ndims = ndims2;
		dims = (int *) palloc(ndims * sizeof(int));
		lbs = (int *) palloc(ndims * sizeof(int));
		memcpy(dims, dims2, ndims * sizeof(int));
		memcpy(lbs, lbs2, ndims * sizeof(int));

		/* increment number of elements in outer array */
		dims[0] += 1;

		/* make sure the added element matches our existing elements */
		for (i = 0; i < ndims1; i++)
		{
			if (dims1[i] != dims[i + 1] || lbs1[i] != lbs[i + 1])
				ereport(ERROR,
						(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
						 errmsg("cannot concatenate incompatible arrays"),
						 errdetail("Arrays with differing dimensions are not "
								   "compatible for concatenation.")));
		}
	}
	else
	{
		/*
		 * (ndims1 == ndims2 + 1)
		 *
		 * resulting array has the first argument as the outer array, with the
		 * second argument appended to the end of the outer dimension
		 */
		ndims = ndims1;
		dims = (int *) palloc(ndims * sizeof(int));
		lbs = (int *) palloc(ndims * sizeof(int));
		memcpy(dims, dims1, ndims * sizeof(int));
		memcpy(lbs, lbs1, ndims * sizeof(int));

		/* increment number of elements in outer array */
		dims[0] += 1;

		/* make sure the added element matches our existing elements */
		for (i = 0; i < ndims2; i++)
		{
			if (dims2[i] != dims[i + 1] || lbs2[i] != lbs[i + 1])
				ereport(ERROR,
						(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
						 errmsg("cannot concatenate incompatible arrays"),
						 errdetail("Arrays with differing dimensions are not "
								   "compatible for concatenation.")));
		}
	}

	/* Do this mainly for overflow checking */
	nitems = ArrayGetNItems(ndims, dims);

	/* build the result array */
	ndatabytes = ndatabytes1 + ndatabytes2;
	if (ARR_HASNULL(v1) || ARR_HASNULL(v2))
	{
		dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
		nbytes = ndatabytes + dataoffset;
	}
	else
	{
		dataoffset = 0;			/* marker for no null bitmap */
		nbytes = ndatabytes + ARR_OVERHEAD_NONULLS(ndims);
	}
	result = (ArrayType *) palloc(nbytes);
	result->size = nbytes;
	result->ndim = ndims;
	result->dataoffset = dataoffset;
	result->elemtype = element_type;
	memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
	memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
	/* data area is arg1 then arg2 */
	memcpy(ARR_DATA_PTR(result), dat1, ndatabytes1);
	memcpy(ARR_DATA_PTR(result) + ndatabytes1, dat2, ndatabytes2);
	/* handle the null bitmap if needed */
	if (ARR_HASNULL(result))
	{
		array_bitmap_copy(ARR_NULLBITMAP(result), 0,
						  bitmap1, 0,
						  nitems1);
		array_bitmap_copy(ARR_NULLBITMAP(result), nitems1,
						  bitmap2, 0,
						  nitems2);
	}

	PG_RETURN_ARRAYTYPE_P(result);
}
Example #26
0
Datum
alpine_miner_nn_ca_change(PG_FUNCTION_ARGS)
{
    ArrayType  *weight_arg, *columns_arg, *input_range_arg, *input_base_arg,*hidden_node_number_arg, *result;
    Datum     *weight_data, *columns_data, *input_range_data, *input_base_data, *hidden_node_number_data, *result_data;
    bool       *weight_nulls, *columns_nulls, *input_range_nulls, *input_base_nulls, *hidden_node_number_nulls,*result_nulls;
	int         weight_count, columns_count, input_range_count, input_base_count, hidden_node_number_count,result_count ;
        Oid         result_eltype;
	int16 result_typlen;
	bool result_typbyval;
	char result_typalign;

	double output_range_arg,output_base_arg, learning_rate_ar, label_arg;
	int hidden_layer_number_arg, output_node_no_arg, set_size_arg;
	bool normalize_arg, numerical_label_arg ;
        int         ndims, *dims, *lbs;

	int i;
	int j;
	int k;

	int all_hidden_node_count;

	int weight_index;
	int hidden_node_number_index = 0;

	bool null_data;
	double * input;
	double * output;
	int * hidden_node_number;
	double *weight;
	double *hidden_node_output;

	double delta = 0.0;
	double total_error = 0.0;
	double * output_error;
	double direct_output_error = 0.0;

	double * hidden_node_error;
	double error_sum = 0.0;

	double current_change = 0.0;
	double threshold_change = 0.0;

	if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3) || PG_ARGISNULL(4) || PG_ARGISNULL(5) || PG_ARGISNULL(6) || PG_ARGISNULL(7) || PG_ARGISNULL(8) || PG_ARGISNULL(9) || PG_ARGISNULL(10) || PG_ARGISNULL(11) || PG_ARGISNULL(12)){
		PG_RETURN_NULL();
	}

        /* get weight_arg args */
        weight_arg = PG_GETARG_ARRAYTYPE_P(0);

	null_data = alpine_miner_deconstruct_array(weight_arg, &weight_data, &weight_nulls,&weight_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

        columns_arg = PG_GETARG_ARRAYTYPE_P(1);
	null_data = alpine_miner_deconstruct_array(columns_arg, &columns_data, &columns_nulls,&columns_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

        /* get input_range_arg args */
        input_range_arg = PG_GETARG_ARRAYTYPE_P(2);
	null_data = alpine_miner_deconstruct_array(input_range_arg, &input_range_data, &input_range_nulls,&input_range_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

        /* get input_base_arg args */
        input_base_arg = PG_GETARG_ARRAYTYPE_P(3);
	null_data = alpine_miner_deconstruct_array(input_base_arg, &input_base_data, &input_base_nulls,&input_base_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

        /* get hidden_node_number_arg args */
        hidden_node_number_arg = PG_GETARG_ARRAYTYPE_P(4);
	null_data = alpine_miner_deconstruct_array(hidden_node_number_arg, &hidden_node_number_data, &hidden_node_number_nulls,&hidden_node_number_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

	hidden_layer_number_arg= PG_GETARG_INT32(5);

	output_range_arg = PG_GETARG_FLOAT8(6);
	output_base_arg = PG_GETARG_FLOAT8(7);
	output_node_no_arg  = PG_GETARG_INT32(8);
	normalize_arg = PG_GETARG_BOOL(9); 
	numerical_label_arg = PG_GETARG_BOOL(10); 
	label_arg = PG_GETARG_FLOAT8(11);
	set_size_arg = PG_GETARG_INT32(12);
	if (set_size_arg <= 0)
	{
		set_size_arg = 1;
	}

#ifdef ALPINE_DEBUG 
	elog(WARNING,"%f",DatumGetFloat8(columns_data[0]));
#endif
	input =  (double*)palloc(columns_count * sizeof(double));;

	output = (double*)palloc(output_node_no_arg * sizeof(double));
	hidden_node_number = (int*) palloc(hidden_node_number_count * sizeof(int));

	weight = (double*)palloc(weight_count * sizeof(double));
	for (i = 0; i < weight_count; i++)
	{
		weight[i] = DatumGetFloat8(weight_data[i]);
	}
	all_hidden_node_count = 0;
	for (i = 0; i < hidden_layer_number_arg; i++)
	{
		hidden_node_number[i] = DatumGetInt32(hidden_node_number_data[i]);
		all_hidden_node_count += hidden_node_number[i];
	}

	hidden_node_output = (double*)palloc(all_hidden_node_count * sizeof(double));


	//caculate input 
        if (normalize_arg) 
        {
            i = 0;
            while (i < columns_count)
            {
                if (DatumGetFloat8(input_range_data[i]) != 0)
                {
                   input[i] = ((DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i]))/DatumGetFloat8(input_range_data[i]));
		}
                else
		{
                   input[i] = (DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i]));
                }
#ifdef ALPINE_DEBUG 
		elog(WARNING, "input:%f", input[i]);
#endif
		i = i + 1;
            }
	}
        else
	{
		i = 0;
        	while (i < columns_count)
		{
               	    input[i] = DatumGetFloat8(columns_data[i]);
               	    i = i + 1;
        	}
	}

	// caculate hidden node output of 1st layer 
        i = 0;
        while (i < hidden_node_number[0])
	{
                hidden_node_output[i] = weight[0+i*(columns_count + 1)];
                j = 0;
                while (j < columns_count)
		{
                        hidden_node_output[i] = hidden_node_output[i]+input[j]*weight[1 + j  + i *(columns_count + 1)];
#ifdef ALPINE_DEBUG 
			elog(WARNING,"hiddensum[%d] input[%d] %f weight[%d] %f", i, j,input[j] , 1+j  +(i)*(columns_count +1), weight[1+j +i*(columns_count + 1)]);
#endif
                        j = j + 1;
		}

		if (hidden_node_output[i] < -45.0)
		{
			hidden_node_output[i] = 0;
		}
		else if (hidden_node_output[i] > 45.0)
		{
			hidden_node_output[i] = 1;
		}
		else
		{
            	    hidden_node_output[i] = (1.0/(1.0+exp( -1.0 * hidden_node_output[i])));
		}
#ifdef ALPINE_DEBUG 
		 elog(WARNING,"hidden[%d] %f", i, hidden_node_output[i]);
#endif
                i = i + 1;
	}
//       calculate hidden layer 2~last output
        weight_index = hidden_node_number[0] * (columns_count + 1) ;

        if (hidden_layer_number_arg > 1)
	{
	        hidden_node_number_index = 0;
	        i = 1;
	        while (i < hidden_layer_number_arg )
		{
	                hidden_node_number_index = hidden_node_number_index + hidden_node_number[i - 1];
	                j = 0;
	                while (j < hidden_node_number[i]) 
			{
	                        hidden_node_output[hidden_node_number_index + j] = weight[weight_index + (hidden_node_number[i - 1] +1) * j];
	                        k = 0;
	                        while (k < hidden_node_number[i - 1])
				{ 
	                                hidden_node_output[hidden_node_number_index + j] = hidden_node_output[hidden_node_number_index + j]+hidden_node_output[hidden_node_number_index - hidden_node_number[i - 1] + k]*weight[weight_index + (hidden_node_number[i - 1] +1) * j + k + 1];
	                                k = k + 1;
				}
				if (hidden_node_output[hidden_node_number_index + j] < -45.0)
				{
					hidden_node_output[hidden_node_number_index + j] = 0;
				}
				else if (hidden_node_output[hidden_node_number_index + j] > 45.0)
				{
					hidden_node_output[hidden_node_number_index + j] = 1;
				}
				else
				{
	                        	hidden_node_output[hidden_node_number_index + j] = (1.0/(1+exp(-1.0*hidden_node_output[hidden_node_number_index+j])));
				}
	                        j = j + 1;
	                }
	                weight_index = weight_index + hidden_node_number[i] * (hidden_node_number[i - 1] + 1);
	                i = i + 1;
	       }
        }

	//compute output value of  output node;
        i = 0;
        while (i < output_node_no_arg)
		{
                output[i] = weight[weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i];
#ifdef ALPINE_DEBUG 
		elog(WARNING,"weightindex:%d,weight[%d] %f",weight_index, weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i, output[i]);
#endif
                j = 0;
                while (j < hidden_node_number[hidden_layer_number_arg-1])
		{
#ifdef ALPINE_DEBUG 
			elog(WARNING,"ouput[%d]:%f ,hidden_node_number_index:%d,j:%d, weight[%d]:%f",i,output[i], hidden_node_number_index ,j,1+j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i , weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ]);
#endif
                        output[i] = output[i]+hidden_node_output[hidden_node_number_index + j]
					* weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ];
                        j = j + 1;
				}
#ifdef ALPINE_DEBUG 
		 elog(WARNING,"ouputsum[%d] %f", i, output[i]);
#endif
		if (numerical_label_arg)
		{
                	output[i] = ((output[i]) * output_range_arg+output_base_arg);
#ifdef ALPINE_DEBUG 
			elog(WARNING,"output:%f, %f,%f",output[i],output_range_arg,output_base_arg);
#endif
		}
		else
		{
			if (output[i] < -45.0)
			{
				output[i] = 0;
			}
			else if (output[i] > 45.0)
			{
				output[i] = 1;
			}
			else
			{
				output[i] = (1.0/(1+exp(-1.0*output[i])));
			}
		}
#ifdef ALPINE_DEBUG 
		 elog(WARNING,"ouputsum2[%d] %f", i, output[i]);
#endif
                i = i + 1;
	}

	/* get output array element type */
	result_eltype = FLOAT8OID;
	get_typlenbyvalalign(result_eltype, &result_typlen, &result_typbyval, &result_typalign);

	/* construct result array */
	result_count = weight_count + 1;
	result_data = (Datum *)palloc(result_count * sizeof(Datum));
	result_nulls = (bool *)palloc(result_count * sizeof(bool));
	for (i = 0; i < result_count; i++)
	{
		result_nulls[i] = false;
	}
	//compute error of output node
	output_error = (double *)palloc(output_node_no_arg * sizeof(double));
	for(i = 0; i < output_node_no_arg; i++)
	{
		if(numerical_label_arg)
		{
			if (output_range_arg == 0.0)
			{
				direct_output_error = 0.0;
			}
			else
			{
				direct_output_error = (label_arg - output[i])/output_range_arg;
			}
			output_error[i] = direct_output_error;
		}
		else
		{
			if (((int)label_arg) == i)
			{
				direct_output_error = 1.0 - output[i];
			}
			else
			{
				direct_output_error = 0.0 - output[i];
			}
#ifdef ALPINE_DEBUG 
		elog(WARNING,"label_arg :%f %d %d", label_arg, i, (((int)label_arg) == i));
#endif
			output_error[i] = direct_output_error * output[i] * (1- output[i]);
		}
		total_error += direct_output_error*direct_output_error;
#ifdef ALPINE_DEBUG 
		elog(WARNING,"output_error[%d] %f  totalerror:%f", i, output_error[i], total_error);
#endif
	}

	//compute hidden_node_error of last layer hidden_node----
	hidden_node_error = (double*)palloc(all_hidden_node_count * sizeof(double));
	weight_index = weight_count - output_node_no_arg*(hidden_node_number[hidden_layer_number_arg - 1] + 1)  ;
	hidden_node_number_index = all_hidden_node_count - hidden_node_number[hidden_layer_number_arg - 1];
	for(i = 0; i < hidden_node_number[hidden_layer_number_arg - 1]; i++)
	{
		error_sum = 0.0;
		for(k = 0; k < output_node_no_arg; k++)
		{
			error_sum = error_sum+output_error[k]*weight[weight_index + (hidden_node_number[hidden_layer_number_arg - 1] + 1)*k + i + 1];
#ifdef ALPINE_DEBUG 
		elog(WARNING,"output_error[%d]:%f,weight[%d]:%f",k,output_error[k],weight_index + (hidden_node_number[hidden_layer_number_arg - 1] + 1)*k + i + 1, weight[weight_index + (hidden_node_number[hidden_layer_number_arg - 1] + 1)*k + i + 1]);
#endif
		}
		hidden_node_error[hidden_node_number_index + i] = error_sum*hidden_node_output[hidden_node_number_index + i]*(1.0-hidden_node_output[hidden_node_number_index + i]);
#ifdef ALPINE_DEBUG 
		elog(WARNING,"hidden_node_error[%d] %f ", hidden_node_number_index+i, hidden_node_error[hidden_node_number_index + i]);
#endif
	}

	//compute hidden_node_error  of 1 layer to the one before last layer hidden node
	if (hidden_layer_number_arg > 1)
	{
		weight_index = weight_index - (hidden_node_number[hidden_layer_number_arg - 2] + 1)*hidden_node_number[hidden_layer_number_arg - 1];
		hidden_node_number_index = hidden_node_number_index - hidden_node_number[hidden_layer_number_arg - 2];
		for(i = hidden_layer_number_arg - 2; i >= 0; i--)
		{
			for(j = 0; j < hidden_node_number[i]; j++)
			{
				error_sum = 0.0;
				for (k = 0; k < hidden_node_number[i + 1]; k++)
				{
					error_sum = error_sum+hidden_node_error[hidden_node_number_index + hidden_node_number[i] + k]*weight[weight_index + (hidden_node_number[i]+1)*(k) + j + 1];
#ifdef ALPINE_DEBUG 
		elog(WARNING,"i:%d j:%d k:%d; hidden_node_error[%d]:%f,weight[%d]:%f",i,j,k,hidden_node_number_index + hidden_node_number[i] + k, hidden_node_error[hidden_node_number_index + hidden_node_number[i] + k], weight_index + (hidden_node_number[i]+1)*(k) + j + 1,weight[weight_index + (hidden_node_number[i]+1)*(k) + j + 1]);
#endif
				}
				hidden_node_error[hidden_node_number_index + j] = error_sum*hidden_node_output[hidden_node_number_index + j]*(1-hidden_node_output[hidden_node_number_index + j]);
#ifdef ALPINE_DEBUG 
                elog(WARNING,"hidden_node_error[%d] %f ", hidden_node_number_index+j, hidden_node_error[hidden_node_number_index + j]);
#endif
			}
			weight_index = weight_index - (hidden_node_number[i - 1]+1) * hidden_node_number[i];
			hidden_node_number_index = hidden_node_number_index - hidden_node_number[i - 1];
		}
	}

	//compute weight change of output node
	weight_index = weight_count - (hidden_node_number[hidden_layer_number_arg - 1]+ 1)* output_node_no_arg;
	hidden_node_number_index = all_hidden_node_count - hidden_node_number[hidden_layer_number_arg - 1];
	for(i = 0; i < output_node_no_arg; i++)
	{
		delta = 1.0/set_size_arg*output_error[i];
		threshold_change = delta;
		result_data[weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i)] = Float8GetDatum(threshold_change);
#ifdef ALPINE_DEBUG 
                elog(WARNING, " result_data [%d] %f ", weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i), threshold_change);
#endif

		for(j = 0; j < hidden_node_number[hidden_layer_number_arg - 1] ; j++)
		{
			current_change = delta * hidden_node_output[hidden_node_number_index + j];
			result_data[weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i) + 1 +j] = Float8GetDatum(current_change);
#ifdef ALPINE_DEBUG 
                elog(WARNING, " result_data [%d] %f , i:%d j:%d output_error[%d]:%f, hidden_node_output[%d]:%f", weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i) + 1+ j, current_change, i,j,i,output_error[i],hidden_node_number_index + j, hidden_node_output[hidden_node_number_index + j]);
#endif
		}
	}

	//compute weight change of hidden node last layer  to  2 layer
	if (hidden_layer_number_arg > 1)
	{
		for(i = hidden_layer_number_arg - 1; i >= 1; i--)
		{
			weight_index = weight_index - (hidden_node_number[i - 1]+1)*hidden_node_number[i];
			hidden_node_number_index = hidden_node_number_index - hidden_node_number[i - 1];
			delta = 0.0;
			for (j = 0; j < hidden_node_number[i]; j++)
			{
				delta = (1.0/set_size_arg*hidden_node_error[hidden_node_number_index + hidden_node_number[i - 1] + j]);
				threshold_change = delta;
				result_data[weight_index + (hidden_node_number[i - 1] + 1) * (j)] = Float8GetDatum(threshold_change);
#ifdef ALPINE_DEBUG 
                elog(WARNING, " result_data [%d] %f ", weight_index + (hidden_node_number[i - 1] + 1) * (j), threshold_change);
#endif
				for(k = 0; k < hidden_node_number[i - 1]; k++)
				{
					current_change = delta * hidden_node_output[hidden_node_number_index + k];
					result_data[weight_index + (hidden_node_number[i - 1] + 1) * (j) + 1 +  k] = Float8GetDatum(current_change);
#ifdef ALPINE_DEBUG 
                elog(WARNING, " result_data [%d] %f i:%d, j:%d k:%d hidden_node_error[%d]:%f hidden_node_output[%d]:%f", weight_index + (hidden_node_number[i - 1] + 1) * (j) + 1 +  k, current_change,i,j,k,hidden_node_number_index + hidden_node_number[i - 1] + j, hidden_node_error[hidden_node_number_index + hidden_node_number[i - 1] + j], hidden_node_number_index + k,hidden_node_output[hidden_node_number_index + k]);
#endif
				}
			}
		}
	}


	//compute weight change of first layer hidden node
	weight_index = 0; 
	hidden_node_number_index = 0;
	delta = 0.0;
	for(j = 0; j < hidden_node_number[0]; j++)
	{
		delta = 1.0/set_size_arg*hidden_node_error[hidden_node_number_index + j];
		threshold_change = delta;
		result_data[weight_index + (columns_count+1)*(j)] = Float8GetDatum(threshold_change);
#ifdef ALPINE_DEBUG 
                elog(WARNING, " result_data [%d] %f ", weight_index + (columns_count+1)*(j), threshold_change);
#endif
		for(k = 0; k < columns_count; k++)
		{
			current_change = delta*input[k];
			result_data[weight_index +  (columns_count+1)*(j) + k + 1] = Float8GetDatum(current_change);
#ifdef ALPINE_DEBUG 
                elog(WARNING, " result_data [%d] %f j:%d k:%d hidden_node_error[%d]:%f input[%d]:%f", weight_index +  (columns_count+1)*(j) + k + 1, current_change,j,k,hidden_node_number_index + j, hidden_node_error[hidden_node_number_index + j], k, input[k]);
#endif
		}
	}

	result_data[weight_count] = Float8GetDatum(total_error);
	ndims = 1;
	dims = (int *) palloc(sizeof(int));
	dims[0] = result_count;
	lbs = (int *) palloc(sizeof(int));
	lbs[0] = 1;

	result = construct_md_array((void *)result_data, result_nulls, ndims, dims,
			lbs, result_eltype, result_typlen, result_typbyval, result_typalign);

//	pfree(result);
	pfree(weight_data);
	pfree(columns_data);
	pfree(input_range_data);
	pfree(input_base_data);
	pfree(hidden_node_number_data);
	pfree(result_data);
	pfree(weight_nulls);
	pfree(columns_nulls);
	pfree(input_range_nulls);
	pfree(input_base_nulls);
	pfree(hidden_node_number_nulls);
	pfree(result_nulls);
	pfree(input);
	pfree(output);
	pfree(lbs);
	pfree(dims);
	pfree(hidden_node_output);
	pfree(weight);
	pfree(hidden_node_number);

	pfree(hidden_node_error);
	pfree(output_error);

        PG_RETURN_ARRAYTYPE_P(result);
}
Example #27
0
Datum
alpine_miner_lr_combine(PG_FUNCTION_ARGS)
{
	ArrayType  *state1, *state2, *result;
	float8     *state1Data, *state2Data, *resultData;
	int         i, size;
	int         statelen;
	
	if (PG_ARGISNULL(0))
	{
		if (PG_ARGISNULL(1))
			PG_RETURN_NULL();
		PG_RETURN_ARRAYTYPE_P(PG_GETARG_ARRAYTYPE_P(1));
	}
	if (PG_ARGISNULL(1))
		PG_RETURN_ARRAYTYPE_P(PG_GETARG_ARRAYTYPE_P(0));
	
	state1 = PG_GETARG_ARRAYTYPE_P(0);	
	state2 = PG_GETARG_ARRAYTYPE_P(1);
	
	if (ARR_NULLBITMAP(state1) || ARR_NULLBITMAP(state2) || 
		ARR_NDIM(state1) != 1 || ARR_NDIM(state2) != 1 || 
		ARR_ELEMTYPE(state1) != FLOAT8OID || ARR_ELEMTYPE(state2) != FLOAT8OID)
	{
		ereport(ERROR, 
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("preliminary segment-level calculation function \"%s\" called with invalid parameters",
					format_procedure(fcinfo->flinfo->fn_oid))));
	}
	
	if (ARR_DIMS(state1)[0] == 1)
		PG_RETURN_ARRAYTYPE_P(state2);
	if (ARR_DIMS(state2)[0] == 1)
		PG_RETURN_ARRAYTYPE_P(state1);
	
	state1Data = (float8*) ARR_DATA_PTR(state1);
	state2Data = (float8*) ARR_DATA_PTR(state2);
	
	if (ARR_DIMS(state1)[0] != ARR_DIMS(state2)[0]) 
	{
		ereport(ERROR, 
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("preliminary segment-level calculation function \"%s\" called with invalid parameters",
					format_procedure(fcinfo->flinfo->fn_oid)),
				 errdetail("The independent-variable array is not of constant width.")));
	}
	statelen = ARR_DIMS(state1)[0];
	size = statelen * sizeof(float8) + ARR_OVERHEAD_NONULLS(1);
	result = (ArrayType *) palloc(size);
	SET_VARSIZE(result, size);
	result->ndim = 1;
	result->dataoffset = 0;
	result->elemtype = FLOAT8OID;
	ARR_DIMS(result)[0] = statelen;
	ARR_LBOUND(result)[0] = 1;
	resultData = (float8*) ARR_DATA_PTR(result);
	memset(resultData, 0, statelen * sizeof(float8));
	
	for (i = 0; i < statelen; i++){
		resultData[i] = state1Data[i] + state2Data[i];	
	}
	PG_RETURN_ARRAYTYPE_P(result);
}
Example #28
0
Datum
hstore_from_arrays(PG_FUNCTION_ARGS)
{
	int4		buflen;
	HStore	   *out;
	Pairs	   *pairs;
	Datum	   *key_datums;
	bool	   *key_nulls;
	int			key_count;
	Datum	   *value_datums;
	bool	   *value_nulls;
	int			value_count;
	ArrayType  *key_array;
	ArrayType  *value_array;
	int			i;

	if (PG_ARGISNULL(0))
		PG_RETURN_NULL();

	key_array = PG_GETARG_ARRAYTYPE_P(0);

	Assert(ARR_ELEMTYPE(key_array) == TEXTOID);

	/*
	 * must check >1 rather than != 1 because empty arrays have 0 dimensions,
	 * not 1
	 */

	if (ARR_NDIM(key_array) > 1)
		ereport(ERROR,
				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
				 errmsg("wrong number of array subscripts")));

	deconstruct_array(key_array,
					  TEXTOID, -1, false, 'i',
					  &key_datums, &key_nulls, &key_count);

	/* value_array might be NULL */

	if (PG_ARGISNULL(1))
	{
		value_array = NULL;
		value_count = key_count;
		value_datums = NULL;
		value_nulls = NULL;
	}
	else
	{
		value_array = PG_GETARG_ARRAYTYPE_P(1);

		Assert(ARR_ELEMTYPE(value_array) == TEXTOID);

		if (ARR_NDIM(value_array) > 1)
			ereport(ERROR,
					(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
					 errmsg("wrong number of array subscripts")));

		if ((ARR_NDIM(key_array) > 0 || ARR_NDIM(value_array) > 0) &&
			(ARR_NDIM(key_array) != ARR_NDIM(value_array) ||
			 ARR_DIMS(key_array)[0] != ARR_DIMS(value_array)[0] ||
			 ARR_LBOUND(key_array)[0] != ARR_LBOUND(value_array)[0]))
			ereport(ERROR,
					(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
					 errmsg("arrays must have same bounds")));

		deconstruct_array(value_array,
						  TEXTOID, -1, false, 'i',
						  &value_datums, &value_nulls, &value_count);

		Assert(key_count == value_count);
	}

	pairs = palloc(key_count * sizeof(Pairs));

	for (i = 0; i < key_count; ++i)
	{
		if (key_nulls[i])
			ereport(ERROR,
					(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
					 errmsg("null value not allowed for hstore key")));

		if (!value_nulls || value_nulls[i])
		{
			pairs[i].key = VARDATA_ANY(key_datums[i]);
			pairs[i].val = NULL;
			pairs[i].keylen = hstoreCheckKeyLen(VARSIZE_ANY_EXHDR(key_datums[i]));
			pairs[i].vallen = 4;
			pairs[i].isnull = true;
			pairs[i].needfree = false;
		}
		else
		{
			pairs[i].key = VARDATA_ANY(key_datums[i]);
			pairs[i].val = VARDATA_ANY(value_datums[i]);
			pairs[i].keylen = hstoreCheckKeyLen(VARSIZE_ANY_EXHDR(key_datums[i]));
			pairs[i].vallen = hstoreCheckValLen(VARSIZE_ANY_EXHDR(value_datums[i]));
			pairs[i].isnull = false;
			pairs[i].needfree = false;
		}
	}

	key_count = hstoreUniquePairs(pairs, key_count, &buflen);

	out = hstorePairs(pairs, key_count, buflen);

	PG_RETURN_POINTER(out);
}
Example #29
0
/*
 * Common subroutine for num_nulls() and num_nonnulls().
 * Returns TRUE if successful, FALSE if function should return NULL.
 * If successful, total argument count and number of nulls are
 * returned into *nargs and *nulls.
 */
static bool
count_nulls(FunctionCallInfo fcinfo,
			int32 *nargs, int32 *nulls)
{
	int32		count = 0;
	int			i;

	/* Did we get a VARIADIC array argument, or separate arguments? */
	if (get_fn_expr_variadic(fcinfo->flinfo))
	{
		ArrayType  *arr;
		int			ndims,
					nitems,
				   *dims;
		bits8	   *bitmap;

		Assert(PG_NARGS() == 1);

		/*
		 * If we get a null as VARIADIC array argument, we can't say anything
		 * useful about the number of elements, so return NULL.  This behavior
		 * is consistent with other variadic functions - see concat_internal.
		 */
		if (PG_ARGISNULL(0))
			return false;

		/*
		 * Non-null argument had better be an array.  We assume that any call
		 * context that could let get_fn_expr_variadic return true will have
		 * checked that a VARIADIC-labeled parameter actually is an array.  So
		 * it should be okay to just Assert that it's an array rather than
		 * doing a full-fledged error check.
		 */
		Assert(OidIsValid(get_base_element_type(get_fn_expr_argtype(fcinfo->flinfo, 0))));

		/* OK, safe to fetch the array value */
		arr = PG_GETARG_ARRAYTYPE_P(0);

		/* Count the array elements */
		ndims = ARR_NDIM(arr);
		dims = ARR_DIMS(arr);
		nitems = ArrayGetNItems(ndims, dims);

		/* Count those that are NULL */
		bitmap = ARR_NULLBITMAP(arr);
		if (bitmap)
		{
			int			bitmask = 1;

			for (i = 0; i < nitems; i++)
			{
				if ((*bitmap & bitmask) == 0)
					count++;

				bitmask <<= 1;
				if (bitmask == 0x100)
				{
					bitmap++;
					bitmask = 1;
				}
			}
		}

		*nargs = nitems;
		*nulls = count;
	}
	else
	{
		/* Separate arguments, so just count 'em */
		for (i = 0; i < PG_NARGS(); i++)
		{
			if (PG_ARGISNULL(i))
				count++;
		}

		*nargs = PG_NARGS();
		*nulls = count;
	}

	return true;
}
Example #30
0
/*
 * array_position_common
 *		Common code for array_position and array_position_start
 *
 * These are separate wrappers for the sake of opr_sanity regression test.
 * They are not strict so we have to test for null inputs explicitly.
 */
static Datum
array_position_common(FunctionCallInfo fcinfo)
{
	ArrayType  *array;
	Oid			collation = PG_GET_COLLATION();
	Oid			element_type;
	Datum		searched_element,
				value;
	bool		isnull;
	int			position,
				position_min;
	bool		found = false;
	TypeCacheEntry *typentry;
	ArrayMetaState *my_extra;
	bool		null_search;
	ArrayIterator array_iterator;

	if (PG_ARGISNULL(0))
		PG_RETURN_NULL();

	array = PG_GETARG_ARRAYTYPE_P(0);
	element_type = ARR_ELEMTYPE(array);

	/*
	 * We refuse to search for elements in multi-dimensional arrays, since we
	 * have no good way to report the element's location in the array.
	 */
	if (ARR_NDIM(array) > 1)
		ereport(ERROR,
				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
				 errmsg("searching for elements in multidimensional arrays is not supported")));

	if (PG_ARGISNULL(1))
	{
		/* fast return when the array doesn't have nulls */
		if (!array_contains_nulls(array))
			PG_RETURN_NULL();
		searched_element = (Datum) 0;
		null_search = true;
	}
	else
	{
		searched_element = PG_GETARG_DATUM(1);
		null_search = false;
	}

	position = (ARR_LBOUND(array))[0] - 1;

	/* figure out where to start */
	if (PG_NARGS() == 3)
	{
		if (PG_ARGISNULL(2))
			ereport(ERROR,
					(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
					 errmsg("initial position must not be null")));

		position_min = PG_GETARG_INT32(2);
	}
	else
		position_min = (ARR_LBOUND(array))[0];

	/*
	 * We arrange to look up type info for array_create_iterator only once per
	 * series of calls, assuming the element type doesn't change underneath
	 * us.
	 */
	my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
	if (my_extra == NULL)
	{
		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
													  sizeof(ArrayMetaState));
		my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
		my_extra->element_type = ~element_type;
	}

	if (my_extra->element_type != element_type)
	{
		get_typlenbyvalalign(element_type,
							 &my_extra->typlen,
							 &my_extra->typbyval,
							 &my_extra->typalign);

		typentry = lookup_type_cache(element_type, TYPECACHE_EQ_OPR_FINFO);

		if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_FUNCTION),
				errmsg("could not identify an equality operator for type %s",
					   format_type_be(element_type))));

		my_extra->element_type = element_type;
		fmgr_info_cxt(typentry->eq_opr_finfo.fn_oid, &my_extra->proc,
					  fcinfo->flinfo->fn_mcxt);
	}

	/* Examine each array element until we find a match. */
	array_iterator = array_create_iterator(array, 0, my_extra);
	while (array_iterate(array_iterator, &value, &isnull))
	{
		position++;

		/* skip initial elements if caller requested so */
		if (position < position_min)
			continue;

		/*
		 * Can't look at the array element's value if it's null; but if we
		 * search for null, we have a hit and are done.
		 */
		if (isnull || null_search)
		{
			if (isnull && null_search)
			{
				found = true;
				break;
			}
			else
				continue;
		}

		/* not nulls, so run the operator */
		if (DatumGetBool(FunctionCall2Coll(&my_extra->proc, collation,
										   searched_element, value)))
		{
			found = true;
			break;
		}
	}

	array_free_iterator(array_iterator);

	/* Avoid leaking memory when handed toasted input */
	PG_FREE_IF_COPY(array, 0);

	if (!found)
		PG_RETURN_NULL();

	PG_RETURN_INT32(position);
}