예제 #1
0
/*-----------------------------------------------------------------------------
 * array_prepend :
 *		push an element onto the front of a one-dimensional array
 *----------------------------------------------------------------------------
 */
Datum
array_prepend(PG_FUNCTION_ARGS)
{
	ArrayType  *v;
	Datum		newelem;
	bool		isNull;
	ArrayType  *result;
	int		   *lb;
	int			indx;
	ArrayMetaState *my_extra;

	isNull = PG_ARGISNULL(0);
	if (isNull)
		newelem = (Datum) 0;
	else
		newelem = PG_GETARG_DATUM(0);
	v = fetch_array_arg_replace_nulls(fcinfo, 1);

	if (ARR_NDIM(v) == 1)
	{
		/* prepend newelem */
		lb = ARR_LBOUND(v);
		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")));

	/* Perform element insertion */
	my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;

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

	/* Readjust result's LB to match the input's, as expected for prepend */
	if (ARR_NDIM(v) == 1)
		ARR_LBOUND(result)[0] = ARR_LBOUND(v)[0];

	PG_RETURN_ARRAYTYPE_P(result);
}
예제 #2
0
void array_loop(ArrayType *array, int32 start, array_iter *iter)
{
	iter->array = array;
	iter->ptr   = ARR_DATA_PTR(array);
	iter->max   = ARR_DIMS(array)[0];
	get_typlenbyvalalign(ARR_ELEMTYPE(array), 
						 &iter->typlen,
						 &iter->typbyval,
						 &iter->typalign);

	/* If we are starting in the middle of the array, then scan forward */
	start = start - ARR_LBOUND(array)[0];
	if (start <= 0)
		iter->index = start;
	else
	{
		/* 
		 * could probably be more efficient for fixed length arrays, but
		 * they would still require adjustments for nulls.
		 */
		iter->index = 0;
		while (start--)
		{
			Datum d;
			bool  isna;
			array_next(iter, &d, &isna);
		}
	}
}
예제 #3
0
파일: array.c 프로젝트: python-postgres/be
static PyObj
array_get_lowerbounds(PyObj self, void *closure)
{
	ArrayType *at;
	PyObj rob;
	int i, ndim, *lbs;

	at = DatumGetArrayTypeP(PyPgObject_GetDatum(self));
	ndim = ARR_NDIM(at);
	lbs = ARR_LBOUND(at);

	rob = PyTuple_New(ndim);

	for (i = 0; i < ndim; ++i)
	{
		PyObj ob;
		ob = PyLong_FromLong(lbs[i]);
		if (ob == NULL)
		{
			Py_DECREF(rob);
			return(NULL);
		}
		PyTuple_SET_ITEM(rob, i, ob);
	}

	return(rob);
}
예제 #4
0
파일: _int_tool.c 프로젝트: Brar/postgres
/* Create a new int array with room for "num" elements */
ArrayType *
new_intArrayType(int num)
{
	ArrayType  *r;
	int			nbytes;

	/* if no elements, return a zero-dimensional array */
	if (num <= 0)
	{
		r = construct_empty_array(INT4OID);
		return r;
	}

	nbytes = ARR_OVERHEAD_NONULLS(1) + sizeof(int) * num;

	r = (ArrayType *) palloc0(nbytes);

	SET_VARSIZE(r, nbytes);
	ARR_NDIM(r) = 1;
	r->dataoffset = 0;			/* marker for no null bitmap */
	ARR_ELEMTYPE(r) = INT4OID;
	ARR_DIMS(r)[0] = num;
	ARR_LBOUND(r)[0] = 1;

	return r;
}
예제 #5
0
파일: table_group.c 프로젝트: kikht/hvault
static int 
intArrayIdx(ArrayType * array, int const * coord, bool noerror)
{
    int * lbs;
    int * dims;
    int i, res;

    lbs = ARR_LBOUND(array);
    dims = ARR_DIMS(array);

    res = 0;
    for (i = 0; i < array->ndim; i++)
    {
        int c = coord[i] - lbs[i];

        if (c < 0 || c >= dims[i])
        {
            if (noerror)
                return -1;
            else
                elog(ERROR, "array out of bounds");
        }
        res = res * dims[i] + c;
    }

    return res;
}
예제 #6
0
파일: Array.c 프로젝트: greenplum-db/pljava
ArrayType* createArrayType(jsize nElems, size_t elemSize, Oid elemType, bool withNulls)
{
	ArrayType* v;
	Size nBytes = elemSize * nElems;
	MemoryContext currCtx = Invocation_switchToUpperContext();

	Size dataoffset;
	if(withNulls)
	{
		dataoffset = ARR_OVERHEAD_WITHNULLS(1, nElems);
		nBytes += dataoffset;
	}
	else
	{
		dataoffset = 0;			/* marker for no null bitmap */
		nBytes += ARR_OVERHEAD_NONULLS(1);
	}
	v = (ArrayType*)palloc0(nBytes);
	AssertVariableIsOfType(v->dataoffset, int32);
	v->dataoffset = (int32)dataoffset;
	MemoryContextSwitchTo(currCtx);

	SET_VARSIZE(v, nBytes);
	ARR_NDIM(v) = 1;
	ARR_ELEMTYPE(v) = elemType;
	*((int*)ARR_DIMS(v)) = nElems;
	*((int*)ARR_LBOUND(v)) = 1;
	return v;
}
예제 #7
0
파일: table_group.c 프로젝트: kikht/hvault
static ArrayType *
intArrayInit(int ndims, int const * dims, int const * lbs)
{
    ArrayType * res;
    int size;
    int nbytes;

    if (ndims < 0)              /* we do allow zero-dimension arrays */
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("invalid number of dimensions: %d", ndims)));
    if (ndims > MAXDIM)
        ereport(ERROR,
                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
                        ndims, MAXDIM)));
    

    /* fast track for empty array */
    if (ndims == 0)
        return construct_empty_array(INT4OID);
    
    size = ArrayGetNItems(ndims, dims);
    nbytes = ARR_OVERHEAD_NONULLS(ndims);
    nbytes += size * 4;
    res = palloc0(nbytes);
    SET_VARSIZE(res, nbytes);
    res->ndim = ndims;
    res->elemtype = INT4OID;
    res->dataoffset = 0;
    memcpy(ARR_DIMS(res), dims, ndims * sizeof(int));
    memcpy(ARR_LBOUND(res), lbs, ndims * sizeof(int));

    return res;
}
예제 #8
0
Datum
hstore_slice_to_array(PG_FUNCTION_ARGS)
{
    HStore	   *hs = PG_GETARG_HS(0);
    HEntry	   *entries = ARRPTR(hs);
    char	   *ptr = STRPTR(hs);
    ArrayType  *key_array = PG_GETARG_ARRAYTYPE_P(1);
    ArrayType  *aout;
    Datum	   *key_datums;
    bool	   *key_nulls;
    Datum	   *out_datums;
    bool	   *out_nulls;
    int			key_count;
    int			i;

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

    if (key_count == 0)
    {
        aout = construct_empty_array(TEXTOID);
        PG_RETURN_POINTER(aout);
    }

    out_datums = palloc(sizeof(Datum) * key_count);
    out_nulls = palloc(sizeof(bool) * key_count);

    for (i = 0; i < key_count; ++i)
    {
        text	   *key = (text *) DatumGetPointer(key_datums[i]);
        int			idx;

        if (key_nulls[i])
            idx = -1;
        else
            idx = hstoreFindKey(hs, NULL, VARDATA(key), VARSIZE(key) - VARHDRSZ);

        if (idx < 0 || HS_VALISNULL(entries, idx))
        {
            out_nulls[i] = true;
            out_datums[i] = (Datum) 0;
        }
        else
        {
            out_datums[i] = PointerGetDatum(
                                cstring_to_text_with_len(HS_VAL(entries, ptr, idx),
                                        HS_VALLEN(entries, idx)));
            out_nulls[i] = false;
        }
    }

    aout = construct_md_array(out_datums, out_nulls,
                              ARR_NDIM(key_array),
                              ARR_DIMS(key_array),
                              ARR_LBOUND(key_array),
                              TEXTOID, -1, false, 'i');

    PG_RETURN_POINTER(aout);
}
예제 #9
0
Datum pcpoint_from_double_array(PG_FUNCTION_ARGS)
{
	uint32 pcid = PG_GETARG_INT32(0);
	ArrayType *arrptr = PG_GETARG_ARRAYTYPE_P(1);
	int nelems;
	float8 *vals;
	PCPOINT *pt;
	PCSCHEMA *schema = pc_schema_from_pcid(pcid, fcinfo);
	SERIALIZED_POINT *serpt;

	if ( ! schema )
		elog(ERROR, "unable to load schema for pcid = %d", pcid);

	if ( ARR_ELEMTYPE(arrptr) != FLOAT8OID )
		elog(ERROR, "array must be of float8[]");

	if ( ARR_NDIM(arrptr) != 1 )
		elog(ERROR, "float8[] must have only one dimension");

	if ( ARR_HASNULL(arrptr) )
		elog(ERROR, "float8[] must not have null elements");

	nelems = ARR_DIMS(arrptr)[0];
	if ( nelems != schema->ndims || ARR_LBOUND(arrptr)[0] > 1 )
		elog(ERROR, "array dimensions do not match schema dimensions of pcid = %d", pcid);

	vals = (float8*) ARR_DATA_PTR(arrptr);
	pt = pc_point_from_double_array(schema, vals, nelems);

	serpt = pc_point_serialize(pt);
	pc_point_free(pt);
	PG_RETURN_POINTER(serpt);
}
예제 #10
0
inline
AbstractionLayer::MutableArrayHandle<T>
AbstractionLayer::Allocator::allocateArray(size_t inNumElements) const {    
    /*
     * Check that the size will not exceed addressable memory. Therefore, the
     * following precondition has to hold:
     * ((std::numeric_limits<size_t>::max() - ARR_OVERHEAD_NONULLS(1)) /
     *     inElementSize >= inNumElements)
     */
    if ((std::numeric_limits<size_t>::max() - ARR_OVERHEAD_NONULLS(1)) /
            sizeof(T) < inNumElements)
        throw std::bad_alloc();
    
    size_t		size = sizeof(T) * inNumElements + ARR_OVERHEAD_NONULLS(1);
    ArrayType	*array;

    // Note: Except for the allocate call, the following statements do not call
    // into the PostgreSQL backend. We are only using macros here.
    
    // PostgreSQL requires that all memory is overwritten with zeros. So
    // we ingore ZM here
    array = static_cast<ArrayType*>(allocate<MC, dbal::DoZero, F>(size));
        
    SET_VARSIZE(array, size);
    array->ndim = 1;
    array->dataoffset = 0;
    array->elemtype = TypeTraits<T>::oid;
    ARR_DIMS(array)[0] = inNumElements;
    ARR_LBOUND(array)[0] = 1;
    
    return MutableArrayHandle<T>(array);
}
예제 #11
0
Datum
alpine_miner_lr_ca_derivative(PG_FUNCTION_ARGS)
{

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

	bool add_intercept_arg;
	double weight_arg;
	int y_arg;
        int         size;

	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;
       	 	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_derivative(columns_count,columns_data, result_data
		,weight_arg, y_arg, add_intercept_arg,  pi);
        PG_RETURN_ARRAYTYPE_P(result);
}
예제 #12
0
Datum
alpine_miner_covar_sam_accum(PG_FUNCTION_ARGS)
{
	ArrayType *state;
	float8 * state_array_data;
	ArrayType * column_array;
	int column_size;
	float8 * column_array_data;
	int i;
	int k ;
	int j;

	if (PG_ARGISNULL(0)){
		 PG_RETURN_NULL();
	}
	state = PG_GETARG_ARRAYTYPE_P(0);
	
	state_array_data = (float8*) ARR_DATA_PTR(state);
	
	column_array = PG_GETARG_ARRAYTYPE_P(1);
	column_size = ARR_DIMS(column_array)[0];
	column_array_data = (float8*) ARR_DATA_PTR(column_array);
	if (ARR_DIMS(state)[0] == 1){
			
			int result_size = column_size * ( column_size + 1)/2 + column_size+2;
       	 	int size =  result_size * sizeof(float8) + ARR_OVERHEAD_NONULLS(1);
        	state = (ArrayType *) palloc(size);
	        SET_VARSIZE(state, size);
       	 	state->ndim = 1;
        	state->dataoffset = 0;
        	state->elemtype = FLOAT8OID;
        	ARR_DIMS(state)[0] = result_size;
        	ARR_LBOUND(state)[0] = 1;
			state_array_data = (float8*) ARR_DATA_PTR(state);
	     	memset(state_array_data, 0,  result_size * sizeof(float8));
	}
	
		k	= 0;
        for ( i = 0; i < column_size; i++){
			for(j = i; j < column_size; j++){
                	state_array_data[k] += column_array_data[i] * column_array_data[j];
			k++;
		}
	}
	for( i = 0; i < column_size; i++){
		state_array_data[k + i] += column_array_data[i];
	}
	state_array_data[k+i]++;
	state_array_data[k+i+1]=column_size;
        PG_RETURN_ARRAYTYPE_P(state);
}	
예제 #13
0
/*-----------------------------------------------------------------------------
 * array_append :
 *		push an element onto the end of a one-dimensional array
 *----------------------------------------------------------------------------
 */
Datum
array_append(PG_FUNCTION_ARGS)
{
	ArrayType  *v;
	Datum		newelem;
	bool		isNull;
	ArrayType  *result;
	int		   *dimv,
			   *lb;
	int			indx;
	ArrayMetaState *my_extra;

	v = fetch_array_arg_replace_nulls(fcinfo, 0);
	isNull = PG_ARGISNULL(1);
	if (isNull)
		newelem = (Datum) 0;
	else
		newelem = PG_GETARG_DATUM(1);

	if (ARR_NDIM(v) == 1)
	{
		/* append newelem */
		int			ub;

		lb = ARR_LBOUND(v);
		dimv = ARR_DIMS(v);
		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 if (ARR_NDIM(v) == 0)
		indx = 1;
	else
		ereport(ERROR,
				(errcode(ERRCODE_DATA_EXCEPTION),
				 errmsg("argument must be empty or one-dimensional array")));

	/* Perform element insertion */
	my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;

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

	PG_RETURN_ARRAYTYPE_P(result);
}
예제 #14
0
파일: kmeans.c 프로젝트: 0x0all/madlib
Datum
internal_get_array_of_close_canopies(PG_FUNCTION_ARGS)
{
    SvecType       *svec;
    Datum          *all_canopies;
    int             num_all_canopies;
    float8          threshold;
    PGFunction      metric_fn;
    
    ArrayType      *close_canopies_arr;
    int4           *close_canopies;
    int             num_close_canopies;
    size_t          bytes;
    MemoryContext   mem_context_for_function_calls;
    
    svec = PG_GETARG_SVECTYPE_P(verify_arg_nonnull(fcinfo, 0));
    get_svec_array_elms(PG_GETARG_ARRAYTYPE_P(verify_arg_nonnull(fcinfo, 1)),
        &all_canopies, &num_all_canopies);
    threshold = PG_GETARG_FLOAT8(verify_arg_nonnull(fcinfo, 2));
    metric_fn = get_metric_fn(PG_GETARG_INT32(verify_arg_nonnull(fcinfo, 3)));
    
    mem_context_for_function_calls = setup_mem_context_for_functional_calls();
    close_canopies = (int4 *) palloc(sizeof(int4) * num_all_canopies);
    num_close_canopies = 0;
    for (int i = 0; i < num_all_canopies; i++) {
        if (compute_metric(metric_fn, mem_context_for_function_calls,
                PointerGetDatum(svec), all_canopies[i]) < threshold)
            close_canopies[num_close_canopies++] = i + 1 /* lower bound */;
    }
    MemoryContextDelete(mem_context_for_function_calls);

    /* If we cannot find any close canopy, return NULL. Note that the result
     * we return will be passed to internal_kmeans_closest_centroid() and if the
     * array of close canopies is NULL, then internal_kmeans_closest_centroid()
     * will consider and compute the distance to all centroids. */
    if (num_close_canopies == 0)
        PG_RETURN_NULL();

    bytes = ARR_OVERHEAD_NONULLS(1) + sizeof(int4) * num_close_canopies;
    close_canopies_arr = (ArrayType *) palloc0(bytes);
    SET_VARSIZE(close_canopies_arr, bytes);
    ARR_ELEMTYPE(close_canopies_arr) = INT4OID;
    ARR_NDIM(close_canopies_arr) = 1;
    ARR_DIMS(close_canopies_arr)[0] = num_close_canopies;
    ARR_LBOUND(close_canopies_arr)[0] = 1;
    memcpy(ARR_DATA_PTR(close_canopies_arr), close_canopies,
        sizeof(int4) * num_close_canopies);

    PG_RETURN_ARRAYTYPE_P(close_canopies_arr);
}
예제 #15
0
Datum
alpine_miner_covar_sam_final(PG_FUNCTION_ARGS){
		ArrayType *state ;
		ArrayType *result;
		float8 * resultData;
		float8 * state_array_data;
		int total_length;
		int column_size;
		float8 row_size;
		int result_size;
		int size;
		int k=0;
		int i,j;
		int sam_row_size;

		if (PG_ARGISNULL(0))
			PG_RETURN_NULL();
		state = PG_GETARG_ARRAYTYPE_P(0);

		state_array_data = (float8*) ARR_DATA_PTR(state);
		total_length=ARR_DIMS(state)[0];


		column_size=state_array_data[total_length-1];
		row_size=state_array_data[total_length-2];
		result_size=column_size*(column_size+1)/2;
		size = result_size * 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_size;
		ARR_LBOUND(result)[0] = 1;
		resultData = (float8*) ARR_DATA_PTR(result);
		memset(resultData, 0, result_size * sizeof(float8));

		 sam_row_size=row_size-1;
		 if(sam_row_size<=0)
		sam_row_size=1;
		  k=0;
		for (  i = 0; i < column_size; i++){
				for(  j = i; j < column_size; j++){
		         	resultData[k] =state_array_data[k]/sam_row_size- state_array_data[result_size+i] * state_array_data[result_size+j]/row_size/sam_row_size;
				k++;
			}
		}
		PG_RETURN_ARRAYTYPE_P(result);

}
예제 #16
0
파일: chunk.c 프로젝트: jarulraj/postgres95
/*------------------------------------------------------------------------
 * _ReadChunkArray1El --
 *       returns one element of the chunked array as specified by the index "st"
 *       the chunked file descriptor is "fp"
 *-------------------------------------------------------------------------
 */
struct varlena *
_ReadChunkArray1El(int st[],
		   int bsize,
		   int fp,
		   ArrayType *array,
		   bool *isNull)
{
    int i, j, n, temp, srcOff;
    int chunk_st[MAXDIM];
    
    int  *C, csize, *dim, *lb;
    int PCHUNK[MAXDIM], PC[MAXDIM];
    
    CHUNK_INFO *A = (CHUNK_INFO *) ARR_DATA_PTR(array);
    
    n = ARR_NDIM(array); 
    lb = ARR_LBOUND(array); 
    C = A->C;
    dim = ARR_DIMS(array);
    
    csize = C[n-1];
    PC[n-1] = 1;
    temp = dim[n - 1]/C[n-1];
    for (i = n-2; i >= 0; i--){
        PC[i] = PC[i+1] * temp;
        temp = dim[i] / C[i];
        csize *= C[i];
    }
    
    for (i = 0; i < n; st[i] -= lb[i], i++);
    mda_get_prod(n, C, PCHUNK);
    
    array2chunk_coord(n, C, st, chunk_st);
    
    for (i = j = 0; i < n; i++)
        j+= chunk_st[i]*PC[i];
    srcOff = j * csize;
    
    for(i = 0; i < n; i++)
        srcOff += (st[i]-chunk_st[i]*C[i])*PCHUNK[i];
    
    srcOff *= bsize;
    if (lo_lseek(fp, srcOff, SEEK_SET) < 0)
	RETURN_NULL;
#ifdef LOARRAY
    return (struct varlena *) LOread(fp, bsize);
#endif
    return (struct varlena *) 0;
}
예제 #17
0
Datum
alpine_plda_count_accum(PG_FUNCTION_ARGS)
{
	ArrayType *state;
	int32 * state_array_data;
	ArrayType * column_array;
	ArrayType * assign_array;
	int32 column_size,assign_size,topicnumber,wordnumber;
	int32 result_size;
	int32 size;
	int32 * column_array_data;
	int32 * assign_array_data;
	int32 k;
	if (PG_ARGISNULL(0)){
		 PG_RETURN_NULL();
	}
	state = PG_GETARG_ARRAYTYPE_P(0);
	
	state_array_data = (int32*) ARR_DATA_PTR(state);
	
	column_array = PG_GETARG_ARRAYTYPE_P(1);
	column_size = ARR_DIMS(column_array)[0];
	column_array_data = (int32*) ARR_DATA_PTR(column_array);
	assign_array=PG_GETARG_ARRAYTYPE_P(2);
	assign_size = ARR_DIMS(assign_array)[0];
	assign_array_data = (int32*) ARR_DATA_PTR(assign_array);
	topicnumber=PG_GETARG_INT32(3);
	wordnumber =PG_GETARG_INT32(4);
	if (ARR_DIMS(state)[0] == 1){
			result_size = topicnumber*wordnumber;
       	 	size =  result_size * sizeof(int32) + ARR_OVERHEAD_NONULLS(1);
         	state = (ArrayType *) palloc(size);
   	        SET_VARSIZE(state, size);
       	 	state->ndim = 1;
        	state->dataoffset = 0;
        	state->elemtype = INT4OID;
        	ARR_DIMS(state)[0] = result_size;
        	ARR_LBOUND(state)[0] = 1;
			state_array_data = (int32*) ARR_DATA_PTR(state);
	     	memset(state_array_data, 0,  result_size * sizeof(int32));
	}

	for ( k = 0; k < column_size; k++){
		state_array_data[topicnumber*(column_array_data[k]-1)+assign_array_data[k]-1]=state_array_data[topicnumber*(column_array_data[k]-1)+assign_array_data[k]-1]+1;
 	}
    PG_RETURN_ARRAYTYPE_P(state);
}	
예제 #18
0
/*
 * flatten_into method for expanded arrays
 */
static void
EA_flatten_into(ExpandedObjectHeader *eohptr,
				void *result, Size allocated_size)
{
	ExpandedArrayHeader *eah = (ExpandedArrayHeader *) eohptr;
	ArrayType  *aresult = (ArrayType *) result;
	int			nelems;
	int			ndims;
	int32		dataoffset;

	Assert(eah->ea_magic == EA_MAGIC);

	/* Easy if we have a valid flattened value */
	if (eah->fvalue)
	{
		Assert(allocated_size == ARR_SIZE(eah->fvalue));
		memcpy(result, eah->fvalue, allocated_size);
		return;
	}

	/* Else allocation should match previous get_flat_size result */
	Assert(allocated_size == eah->flat_size);

	/* Fill result array from dvalues/dnulls */
	nelems = eah->nelems;
	ndims = eah->ndims;

	if (eah->dnulls)
		dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nelems);
	else
		dataoffset = 0;			/* marker for no null bitmap */

	/* We must ensure that any pad space is zero-filled */
	memset(aresult, 0, allocated_size);

	SET_VARSIZE(aresult, allocated_size);
	aresult->ndim = ndims;
	aresult->dataoffset = dataoffset;
	aresult->elemtype = eah->element_type;
	memcpy(ARR_DIMS(aresult), eah->dims, ndims * sizeof(int));
	memcpy(ARR_LBOUND(aresult), eah->lbound, ndims * sizeof(int));

	CopyArrayEls(aresult,
				 eah->dvalues, eah->dnulls, nelems,
				 eah->typlen, eah->typbyval, eah->typalign,
				 false);
}
예제 #19
0
파일: cdbcat.c 프로젝트: BenjaminYu/gpdb
/*
 * Extract len and pointer to buffer from an int16[] (vector) Datum
 * representing a PostgreSQL INT2OID type.
 */
static void
extract_INT2OID_array(Datum array_datum, int *lenp, int16 **vecp)
{
	ArrayType  *array_type;

	Assert(lenp != NULL);
	Assert(vecp != NULL);

	array_type = DatumGetArrayTypeP(array_datum);
	Assert(ARR_NDIM(array_type) == 1);
	Assert(ARR_ELEMTYPE(array_type) == INT2OID);
	Assert(ARR_LBOUND(array_type)[0] == 1);
	*lenp = ARR_DIMS(array_type)[0];
	*vecp = (int16 *) ARR_DATA_PTR(array_type);

	return;
}
예제 #20
0
static PyObject *
PLyList_FromArray(PLyDatumToOb *arg, Datum d)
{
	ArrayType  *array = DatumGetArrayTypeP(d);
	PLyDatumToOb *elm = arg->elm;
	PyObject   *list;
	int			length;
	int			lbound;
	int			i;

	if (ARR_NDIM(array) == 0)
		return PyList_New(0);

	if (ARR_NDIM(array) != 1)
		ereport(ERROR,
				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
			  errmsg("cannot convert multidimensional array to Python list"),
			  errdetail("PL/Python only supports one-dimensional arrays.")));

	length = ARR_DIMS(array)[0];
	lbound = ARR_LBOUND(array)[0];
	list = PyList_New(length);
	if (list == NULL)
		PLy_elog(ERROR, "could not create new Python list");

	for (i = 0; i < length; i++)
	{
		Datum		elem;
		bool		isnull;
		int			offset;

		offset = lbound + i;
		elem = array_ref(array, 1, &offset, arg->typlen,
						 elm->typlen, elm->typbyval, elm->typalign,
						 &isnull);
		if (isnull)
		{
			Py_INCREF(Py_None);
			PyList_SET_ITEM(list, i, Py_None);
		}
		else
			PyList_SET_ITEM(list, i, elm->func(elm, elem));
	}

	return list;
}
예제 #21
0
파일: _int_tool.c 프로젝트: kjkszpj/PG-SQL
/* Create a new int array with room for "num" elements */
ArrayType *
new_intArrayType(int num)
{
	ArrayType  *r;
	int			nbytes = ARR_OVERHEAD_NONULLS(1) + sizeof(int) * num;

	r = (ArrayType *) palloc0(nbytes);

	SET_VARSIZE(r, nbytes);
	ARR_NDIM(r) = 1;
	r->dataoffset = 0;			/* marker for no null bitmap */
	ARR_ELEMTYPE(r) = INT4OID;
	ARR_DIMS(r)[0] = num;
	ARR_LBOUND(r)[0] = 1;

	return r;
}
예제 #22
0
파일: int.c 프로젝트: colinet/sqlix
/*
 *		int2vectorrecv			- converts external binary format to int2_vector_s
 */
datum_t int2vectorrecv(PG_FUNC_ARGS)
{
	struct string* buf = (struct string*) ARG_POINTER(0);
	struct fc_info locfcinfo;
	int2_vector_s *result;

	/*
	 * Normally one would call array_recv() using DIRECT_FC3, but
	 * that does not work since array_recv wants to cache some data using
	 * fcinfo->flinfo->fn_extra.  So we need to pass it our own flinfo
	 * parameter.
	 */
	INIT_FC_INFO(locfcinfo, fcinfo->flinfo, 3, INVALID_OID, NULL, NULL);

	locfcinfo.arg[0] = PTR_TO_D(buf);
	locfcinfo.arg[1] = OID_TO_D(INT2OID);
	locfcinfo.arg[2] = INT32_TO_D(-1);

	locfcinfo.argnull[0] = false;
	locfcinfo.argnull[1] = false;
	locfcinfo.argnull[2] = false;

	result = (int2_vector_s *) D_TO_PTR(array_recv(&locfcinfo));

	ASSERT(!locfcinfo.isnull);

	/* sanity checks: int2_vector_s must be 1-D, 0-based, no nulls */
	if (ARR_NDIM(result) != 1
		|| ARR_HASNULL(result)
		|| ARR_ELEMTYPE(result) != INT2OID
		|| ARR_LBOUND(result)[0] != 0) {
		ereport(ERROR, (
		errcode(E_INVALID_BINARY_REPRESENTATION),
		errmsg("invalid int2_vector_s data")));
	}

	/* check length for consistency with int2vectorin() */
	if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS) {
		ereport(ERROR, (
		errcode(E_INVALID_PARAMETER_VALUE),
		errmsg("oidvector has too many elements")));
	}

	RET_POINTER(result);
}
예제 #23
0
/*
 *		int2vectorrecv			- converts external binary format to int2vector
 */
Datum
int2vectorrecv(PG_FUNCTION_ARGS)
{
	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
	FunctionCallInfoData locfcinfo;
	int2vector *result;

	/*
	 * Normally one would call array_recv() using DirectFunctionCall3, but
	 * that does not work since array_recv wants to cache some data using
	 * fcinfo->flinfo->fn_extra.  So we need to pass it our own flinfo
	 * parameter.
	 */
	InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3,
							 InvalidOid, NULL, NULL);

	locfcinfo.arg[0] = PointerGetDatum(buf);
	locfcinfo.arg[1] = ObjectIdGetDatum(INT2OID);
	locfcinfo.arg[2] = Int32GetDatum(-1);
	locfcinfo.argnull[0] = false;
	locfcinfo.argnull[1] = false;
	locfcinfo.argnull[2] = false;

	result = (int2vector *) DatumGetPointer(array_recv(&locfcinfo));

	Assert(!locfcinfo.isnull);

	/* sanity checks: int2vector must be 1-D, 0-based, no nulls */
	if (ARR_NDIM(result) != 1 ||
		ARR_HASNULL(result) ||
		ARR_ELEMTYPE(result) != INT2OID ||
		ARR_LBOUND(result)[0] != 0)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
				 errmsg("invalid int2vector data")));

	/* check length for consistency with int2vectorin() */
	if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("oidvector has too many elements")));

	PG_RETURN_POINTER(result);
}
예제 #24
0
파일: pguri.c 프로젝트: dylex/huzblem
Datum domainname_parts(PG_FUNCTION_ARGS)
{
	text *in = PG_GETARG_TEXT_P(0);
	const char *s = VARDATA(in);
	const char *b = s, *p = s, *e = s + VARSIZE_ANY_EXHDR(in);
	int nelems = 0;
	int nbytes = ARR_OVERHEAD_NONULLS(1);
	ArrayType *r;
	char *o;

	while (p < e) 
	{
		b = p;
		STRSEARCH(p, e-p, *p == '.');
		nelems ++;
		nbytes += VARHDRSZ + (p-b);
		nbytes = INTALIGN(nbytes);
		p ++;
	}
	r = (ArrayType *)palloc(nbytes);
	SET_VARSIZE(r, nbytes);
	r->ndim = 1;
	r->dataoffset = 0;
	r->elemtype = TEXTOID;
	*ARR_DIMS(r) = nelems;
	*ARR_LBOUND(r) = 1;

	p = s;
	o = ARR_DATA_PTR(r);
	while (p < e)
	{
		b = p;
		STRSEARCH(p, e-p, *p == '.');
		SET_VARSIZE(o, VARHDRSZ+(p-b));
		o = VARDATA(o);
		memcpy(o, b, p-b);
		o += INTALIGN(p-b);
		p ++;
	}

	PG_FREE_IF_COPY(in, 0);
	PG_RETURN_ARRAYTYPE_P(r);
}
예제 #25
0
inline
MutableArrayHandle<T>
Allocator::internalAllocateArray(
    const std::array<std::size_t, Dimensions>& inNumElements) const {

    std::size_t numElements = Dimensions ? 1 : 0;
    for (std::size_t i = 0; i < Dimensions; ++i)
        numElements *= inNumElements[i];

    /*
     * Check that the size will not exceed addressable memory. Therefore, the
     * following precondition has to hold:
     * ((std::numeric_limits<std::size_t>::max()
     *     - ARR_OVERHEAD_NONULLS(Dimensions)) / inElementSize >= numElements)
     */
    if ((std::numeric_limits<std::size_t>::max()
        - ARR_OVERHEAD_NONULLS(Dimensions)) / sizeof(T) < numElements)
        throw std::bad_alloc();

    std::size_t size = sizeof(T) * numElements
        + ARR_OVERHEAD_NONULLS(Dimensions);
    ArrayType *array;

    // Note: Except for the allocate call, the following statements do not call
    // into the PostgreSQL backend. We are only using macros here.

    // PostgreSQL requires that all memory is overwritten with zeros. So
    // we ingore ZM here
    array = static_cast<ArrayType*>(allocate<MC, dbal::DoZero, F>(size));

    SET_VARSIZE(array, size);
    array->ndim = Dimensions;
    array->dataoffset = 0;
    array->elemtype = TypeTraits<T>::oid;
    for (std::size_t i = 0; i < Dimensions; ++i) {
        ARR_DIMS(array)[i] = static_cast<int>(inNumElements[i]);
        ARR_LBOUND(array)[i] = 1;
    }

    return MutableArrayHandle<T>(array);
}
예제 #26
0
파일: kmeans.c 프로젝트: 0x0all/madlib
Datum
internal_kmeans_canopy_transition(PG_FUNCTION_ARGS) {
    ArrayType      *canopies_arr;
    Datum          *canopies;
    int             num_canopies;
    SvecType       *point;
    PGFunction      metric_fn;
    float8          threshold;

    MemoryContext   mem_context_for_function_calls;
    
    canopies_arr = PG_GETARG_ARRAYTYPE_P(verify_arg_nonnull(fcinfo, 0));
    get_svec_array_elms(canopies_arr, &canopies, &num_canopies);
    point = PG_GETARG_SVECTYPE_P(verify_arg_nonnull(fcinfo, 1));
    metric_fn = get_metric_fn(PG_GETARG_INT32(verify_arg_nonnull(fcinfo, 2)));
    threshold = PG_GETARG_FLOAT8(verify_arg_nonnull(fcinfo, 3));
    
    mem_context_for_function_calls = setup_mem_context_for_functional_calls();
    for (int i = 0; i < num_canopies; i++) {
        if (compute_metric(metric_fn, mem_context_for_function_calls,
            PointerGetDatum(point), canopies[i]) < threshold)
            PG_RETURN_ARRAYTYPE_P(canopies_arr);
    }
    MemoryContextDelete(mem_context_for_function_calls);
    
    int idx = (ARR_NDIM(canopies_arr) == 0)
        ? 1
        : ARR_LBOUND(canopies_arr)[0] + ARR_DIMS(canopies_arr)[0];
    return PointerGetDatum(
        array_set(
            canopies_arr, /* array: the initial array object (mustn't be NULL) */
            1, /* nSubscripts: number of subscripts supplied */
            &idx, /* indx[]: the subscript values */
            PointerGetDatum(point), /* dataValue: the datum to be inserted at the given position */
            false, /* isNull: whether dataValue is NULL */
            -1, /* arraytyplen: pg_type.typlen for the array type */
            -1, /* elmlen: pg_type.typlen for the array's element type */
            false, /* elmbyval: pg_type.typbyval for the array's element type */
            'd') /* elmalign: pg_type.typalign for the array's element type */
        );
}
예제 #27
0
Datum
plr_array_push(PG_FUNCTION_ARGS)
{
	ArrayType  *v;
	Datum		newelem;
	int		   *dimv,
			   *lb, ub;
	ArrayType  *result;
	int			indx;
	Oid			element_type;
	int16		typlen;
	bool		typbyval;
	char		typalign;

	v = PG_GETARG_ARRAYTYPE_P(0);
	newelem = PG_GETARG_DATUM(1);

	/* Sanity check: do we have a one-dimensional array */
	if (ARR_NDIM(v) != 1)
		ereport(ERROR,
				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
				 errmsg("input must be one-dimensional array")));

	lb = ARR_LBOUND(v);
	dimv = ARR_DIMS(v);
	ub = dimv[0] + lb[0] - 1;
	indx = ub + 1;

	element_type = ARR_ELEMTYPE(v);
	/* Sanity check: do we have a non-zero element type */
	if (element_type == 0)
		/* internal error */
		elog(ERROR, "invalid array element type");

	get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);

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

	PG_RETURN_ARRAYTYPE_P(result);
}
예제 #28
0
/*-----------------------------------------------------------------------------
 * 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);
}
예제 #29
0
/*-----------------------------------------------------------------------------
 * 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);
	SET_VARSIZE(result, 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);
}
예제 #30
0
파일: hstore_io.c 프로젝트: d/gpdb
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);
}