/* * extractValue support function */ Datum ginarrayextract(PG_FUNCTION_ARGS) { /* Make copy of array input to ensure it doesn't disappear while in use */ ArrayType *array = PG_GETARG_ARRAYTYPE_P_COPY(0); int32 *nkeys = (int32 *) PG_GETARG_POINTER(1); bool **nullFlags = (bool **) PG_GETARG_POINTER(2); int16 elmlen; bool elmbyval; char elmalign; Datum *elems; bool *nulls; int nelems; get_typlenbyvalalign(ARR_ELEMTYPE(array), &elmlen, &elmbyval, &elmalign); deconstruct_array(array, ARR_ELEMTYPE(array), elmlen, elmbyval, elmalign, &elems, &nulls, &nelems); *nkeys = nelems; *nullFlags = nulls; /* we should not free array, elems[i] points into it */ PG_RETURN_POINTER(elems); }
/* * extractQuery support function */ Datum ginqueryarrayextract(PG_FUNCTION_ARGS) { /* Make copy of array input to ensure it doesn't disappear while in use */ ArrayType *array = PG_GETARG_ARRAYTYPE_P_COPY(0); int32 *nkeys = (int32 *) PG_GETARG_POINTER(1); StrategyNumber strategy = PG_GETARG_UINT16(2); /* bool **pmatch = (bool **) PG_GETARG_POINTER(3); */ /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */ bool **nullFlags = (bool **) PG_GETARG_POINTER(5); int32 *searchMode = (int32 *) PG_GETARG_POINTER(6); int16 elmlen; bool elmbyval; char elmalign; Datum *elems; bool *nulls; int nelems; get_typlenbyvalalign(ARR_ELEMTYPE(array), &elmlen, &elmbyval, &elmalign); deconstruct_array(array, ARR_ELEMTYPE(array), elmlen, elmbyval, elmalign, &elems, &nulls, &nelems); *nkeys = nelems; *nullFlags = nulls; switch (strategy) { case GinOverlapStrategy: *searchMode = GIN_SEARCH_MODE_DEFAULT; break; case GinContainsStrategy: if (nelems > 0) *searchMode = GIN_SEARCH_MODE_DEFAULT; else /* everything contains the empty set */ *searchMode = GIN_SEARCH_MODE_ALL; break; case GinContainedStrategy: /* empty set is contained in everything */ *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY; break; case GinEqualStrategy: if (nelems > 0) *searchMode = GIN_SEARCH_MODE_DEFAULT; else *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY; break; default: elog(ERROR, "ginqueryarrayextract: unknown strategy number: %d", strategy); } /* we should not free array, elems[i] points into it */ PG_RETURN_POINTER(elems); }
Datum cword_count(PG_FUNCTION_ARGS) { ArrayType * count_arr, * doc_arr, * topics_arr; int32 * count, * doc, * topics; int32 doclen, num_topics, dsize, i; Datum * array; int32 idx; if (!(fcinfo->context && IsA(fcinfo->context, AggState))) elog(ERROR, "cword_count not used as part of an aggregate"); doclen = PG_GETARG_INT32(3); num_topics = PG_GETARG_INT32(4); dsize = PG_GETARG_INT32(5); /* Construct a zero'd array at the first call of this function */ if (PG_ARGISNULL(0)) { array = palloc0(dsize*num_topics*sizeof(Datum)); count_arr = construct_array(array,dsize*num_topics,INT4OID,4,true,'i'); } else { count_arr = PG_GETARG_ARRAYTYPE_P(0); } doc_arr = PG_GETARG_ARRAYTYPE_P(1); topics_arr = PG_GETARG_ARRAYTYPE_P(2); /* Check that the input arrays are of the right dimension and type */ if (ARR_NDIM(count_arr) != 1 || ARR_ELEMTYPE(count_arr) != INT4OID || ARR_NDIM(doc_arr) != 1 || ARR_ELEMTYPE(doc_arr) != INT4OID || ARR_NDIM(topics_arr) != 1 || ARR_ELEMTYPE(topics_arr) != INT4OID) ereport (ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("transition function \"%s\" called with invalid parameters", format_procedure(fcinfo->flinfo->fn_oid)))); count = (int32 *)ARR_DATA_PTR(count_arr); doc = (int32 *)ARR_DATA_PTR(doc_arr); topics = (int32 *)ARR_DATA_PTR(topics_arr); /* Update the word-topic count */ for (i=0; i!=doclen; i++) { idx = (doc[i]-1) * num_topics + (topics[i]-1); if (idx < 0 || idx >= dsize*num_topics) ereport (ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("function \"%s\" called with invalid parameters", format_procedure(fcinfo->flinfo->fn_oid)))); count[idx]++; } PG_RETURN_BYTEA_P(count_arr); }
Datum alpine_miner_kmeans_distance_result(PG_FUNCTION_ARGS) { ArrayType *sample_arg, *data_arg; Datum *sample_data, *data_data; Oid sample_eltype,data_eltype; int16 sample_typlen, data_typlen; bool sample_typbyval, data_typbyval; char sample_typalign, data_typalign; bool *sample_nulls, *data_nulls; int sample_count, data_count,k,distanceMode; float len; if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2)||PG_ARGISNULL(3) ) { PG_RETURN_NULL(); } /* get sample_arg args */ sample_arg=PG_GETARG_ARRAYTYPE_P(0); /* get sample_arg array element type */ sample_eltype = ARR_ELEMTYPE(sample_arg); get_typlenbyvalalign(sample_eltype, &sample_typlen, &sample_typbyval, &sample_typalign); deconstruct_array(sample_arg, sample_eltype, sample_typlen, sample_typbyval, sample_typalign, &sample_data, &sample_nulls, &sample_count); /* get data_arg args */ data_arg = PG_GETARG_ARRAYTYPE_P(1); /* get data_arg array element type */ data_eltype = ARR_ELEMTYPE(data_arg); get_typlenbyvalalign(data_eltype, &data_typlen, &data_typbyval, &data_typalign); deconstruct_array(data_arg, data_eltype, data_typlen, data_typbyval, data_typalign, &data_data, &data_nulls, &data_count); k=PG_GETARG_INT32(2); distanceMode=PG_GETARG_INT32(3); len=alpine_miner_resultEuclideanDistance(sample_data,sample_count,data_data,data_count,k,distanceMode); pfree(sample_data); pfree(sample_nulls); pfree(data_data); pfree(data_nulls); PG_RETURN_FLOAT8(len); }
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); }
/* * 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, 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, no nulls */ if (ARR_NDIM(result) != 1 || ARR_HASNULL(result) || ARR_ELEMTYPE(result) != INT2OID) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid int2vector data"))); PG_RETURN_POINTER(result); }
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); } } }
void dump_bvf1_inputs(ArrayType *broker_list_p, text *sector_name_p) { int ndim, nitems; int *dim; int16 typlen; bool typbyval; char typalign; int i; char *broker_list; ndim = ARR_NDIM(broker_list_p); dim = ARR_DIMS(broker_list_p); nitems = ArrayGetNItems(ndim, dim); get_typlenbyvalalign(ARR_ELEMTYPE(broker_list_p), &typlen, &typbyval, &typalign); broker_list = ARR_DATA_PTR(broker_list_p); elog(NOTICE, "BVF1: INPUTS START"); for (i = 0; i < nitems; i++) { elog(NOTICE, "BVF1: broker_list[%d] %s", i, DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(broker_list)))); broker_list = att_addlength_pointer(broker_list, typlen, broker_list); broker_list = (char *) att_align_nominal(broker_list, typalign); } elog(NOTICE, "BVF1: sector_name %s", DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(sector_name_p)))); elog(NOTICE, "BVF1: INPUTS END"); }
/* 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; }
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; }
Datum svec_cast_float8arr(PG_FUNCTION_ARGS) { ArrayType *A_PG = PG_GETARG_ARRAYTYPE_P(0); SvecType *output_svec; if (ARR_ELEMTYPE(A_PG) != FLOAT8OID) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("svec_cast_float8arr only defined over float8[]"))); if (ARR_NDIM(A_PG) != 1) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("svec_cast_float8arr only defined over 1 dimensional arrays")) ); if (ARR_NULLBITMAP(A_PG)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("svec_cast_float8arr does not allow null bitmaps on arrays")) ); /* Extract array */ { int dimension = ARR_DIMS(A_PG)[0]; float8 *array = (float8 *)ARR_DATA_PTR(A_PG); /* Create the output SVEC */ SparseData sdata = float8arr_to_sdata(array,dimension); output_svec = svec_from_sparsedata(sdata,true); } PG_RETURN_SVECTYPE_P(output_svec); }
/* * cms_topn_frequency is a user-facing UDF which returns the estimated frequency * of an item. The first parameter is for CmsTopn and second is for the item to * return the frequency. */ Datum cms_topn_frequency(PG_FUNCTION_ARGS) { CmsTopn *cmsTopn = (CmsTopn *) PG_GETARG_VARLENA_P(0); ArrayType *topnArray = TopnArray(cmsTopn); Datum item = PG_GETARG_DATUM(1); Oid itemType = get_fn_expr_argtype(fcinfo->flinfo, 1); TypeCacheEntry *itemTypeCacheEntry = NULL; Frequency frequency = 0; if (itemType == InvalidOid) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("could not determine input data types"))); } if (topnArray != NULL && itemType != ARR_ELEMTYPE(topnArray)) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Not proper type for this cms_topn"))); } itemTypeCacheEntry = lookup_type_cache(itemType, 0); frequency = CmsTopnEstimateItemFrequency(cmsTopn, item, itemTypeCacheEntry); PG_RETURN_INT32(frequency); }
/* * pivot_find() - Searchs an array of labels for a matching value. * * Returns: index of found value, or -1 if not found * * It may eventually do something smarter than a linear scan, but * for now this is sufficient given that we don't know anything about the * order of 'labels'. * */ static int pivot_find(ArrayType *labels, text *attr) { char *labelsp; int i, nelem, asize; int16 typlen; bool typbyval; char typalign; if (ARR_ELEMTYPE(labels) != TEXTOID) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("pivot_accum: labels are not type text"))); /* Text alignment properties */ get_typlenbyvalalign(TEXTOID, &typlen, &typbyval, &typalign); /* Get the size of the input attribute, we'll use this for fast compares */ asize = VARSIZE(attr); /* The labels array is an array of varying length text, scan it adding the length of the previous entry until we are done or we have found a match. */ labelsp = (char *) ARR_DATA_PTR(labels); nelem = ARR_DIMS(labels)[0]; for (i = 0; i < nelem; i++) { int lsize = VARSIZE(labelsp); if (asize == lsize && !memcmp(attr, labelsp, lsize)) return i; /* Found */ labelsp = labelsp + lsize; labelsp = (char*) att_align(labelsp, typalign); } return -1; /* Not found */ }
Datum array_quantile(PG_FUNCTION_ARGS) { // The formal PostgreSQL array object ArrayType *array; // The array element type Oid arrayElementType; // The array element type width int16 arrayElementTypeWidth; // The array element type "is passed by value" flags (not used, should always be true) bool arrayElementTypeByValue; // The array element type alignment codes (not used) char arrayElementTypeAlignmentCode; // The array contents, as PostgreSQL "datum" objects Datum *arrayContent; // List of "is null" flags for the array contents bool *arrayNullFlags; // The size of each array int arrayLength; int i,j, nelem; double median, mad, f, quantile; double *inarray; if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) ereport(ERROR, (errmsg("Null arrays not accepted"))); // Get array and quantile from input array = PG_GETARG_ARRAYTYPE_P(0); f = PG_GETARG_FLOAT8(1); if (ARR_NDIM(array) != 1) ereport(ERROR, (errmsg("One-dimesional arrays are required"))); if (array_contains_nulls(array)) ereport(ERROR, (errmsg("Array contains null elements"))); arrayLength = (ARR_DIMS(array))[0]; arrayElementType = ARR_ELEMTYPE(array); get_typlenbyvalalign(arrayElementType, &arrayElementTypeWidth, &arrayElementTypeByValue, &arrayElementTypeAlignmentCode); deconstruct_array(array, arrayElementType, arrayElementTypeWidth, arrayElementTypeByValue, arrayElementTypeAlignmentCode, &arrayContent, &arrayNullFlags, &arrayLength); inarray = (double*)malloc(arrayLength*sizeof(double)); for (i=0; i<arrayLength; i++) { inarray[i] = DatumGetFloat4(arrayContent[i]); } gsl_sort (inarray, 1, arrayLength); quantile = gsl_stats_quantile_from_sorted_data(inarray, 1, arrayLength, f); PG_RETURN_FLOAT8(quantile); }
/* * Function used as extractValue and extractQuery both */ Datum ginarrayextract(PG_FUNCTION_ARGS) { ArrayType *array; int32 *nentries = (int32 *) PG_GETARG_POINTER(1); Datum *entries = NULL; int16 elmlen; bool elmbyval; char elmalign; /* * we should guarantee that array will not be destroyed during all * operation */ array = PG_GETARG_ARRAYTYPE_P_COPY(0); ARRAYCHECK(array); get_typlenbyvalalign(ARR_ELEMTYPE(array), &elmlen, &elmbyval, &elmalign); deconstruct_array(array, ARR_ELEMTYPE(array), elmlen, elmbyval, elmalign, &entries, NULL, (int *) nentries); if (*nentries == 0 && PG_NARGS() == 3) { switch (PG_GETARG_UINT16(2)) /* StrategyNumber */ { case GinOverlapStrategy: *nentries = -1; /* nobody can be found */ break; case GinContainsStrategy: case GinContainedStrategy: case GinEqualStrategy: default: /* require fullscan: GIN can't find void * arrays */ break; } } /* we should not free array, entries[i] points into it */ PG_RETURN_POINTER(entries); }
/* * Find 'findelem' within array 'v'. Returns -1 if not found in an array * without any NULL elements, NULL if not found but one or more NULLs appeared * in the array. * * Declared STRICT, must not be called with NULL input(s). */ Datum array_idx(PG_FUNCTION_ARGS) { Datum findelem = PG_GETARG_DATUM(0); ArrayType *v = PG_GETARG_ARRAYTYPE_P(1); 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; Oid element_type; int16 typlen; bool typbyval; char typalign; Datum *elems; bool *nulls; int nelems; Datum cur_elem; bool has_nulls; int i; if (ARR_NDIM(v) == 0) PG_RETURN_NULL(); else if (ARR_NDIM(v) != 1) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("idx(...) only makes sense for one-dimensional arrays, not %i", ARR_NDIM(v)))); element_type = ARR_ELEMTYPE(v); /* For optimal performance we'd get this from a syscache or cache it in the function * call context; see array_push in src/backend/utils/adt/array_userfuncs.c */ get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign); deconstruct_array(v, element_type, typlen, typbyval, typalign, &elems, &nulls, &nelems); has_nulls = false; for (i = 0; i < nelems; i++) { has_nulls |= nulls[i]; cur_elem = elems[i]; /* Compare find_elem for equality against cur_elem */ PG_RETURN_INT(i+1); } if (has_nulls) PG_RETURN_NULL(); else PG_RETURN_INT(-1); }
/** * Convert postgres Datum into a ConcreteValue object. */ AbstractValueSPtr AbstractPGValue::DatumToValue(bool inMemoryIsWritable, Oid inTypeID, Datum inDatum) const { // First check if datum is rowtype if (type_is_rowtype(inTypeID)) { HeapTupleHeader pgTuple = DatumGetHeapTupleHeader(inDatum); return AbstractValueSPtr(new PGValue<HeapTupleHeader>(pgTuple)); } else if (type_is_array(inTypeID)) { ArrayType *pgArray = DatumGetArrayTypeP(inDatum); if (ARR_NDIM(pgArray) != 1) throw std::invalid_argument("Multidimensional arrays not yet supported"); if (ARR_HASNULL(pgArray)) throw std::invalid_argument("Arrays with NULLs not yet supported"); switch (ARR_ELEMTYPE(pgArray)) { case FLOAT8OID: { MemHandleSPtr memoryHandle(new PGArrayHandle(pgArray)); if (inMemoryIsWritable) { return AbstractValueSPtr( new ConcreteValue<Array<double> >( Array<double>(memoryHandle, boost::extents[ ARR_DIMS(pgArray)[0] ]) ) ); } else { return AbstractValueSPtr( new ConcreteValue<Array_const<double> >( Array_const<double>(memoryHandle, boost::extents[ ARR_DIMS(pgArray)[0] ]) ) ); } } } } switch (inTypeID) { case BOOLOID: return AbstractValueSPtr( new ConcreteValue<bool>( DatumGetBool(inDatum) )); case INT2OID: return AbstractValueSPtr( new ConcreteValue<int16_t>( DatumGetInt16(inDatum) )); case INT4OID: return AbstractValueSPtr( new ConcreteValue<int32_t>( DatumGetInt32(inDatum) )); case INT8OID: return AbstractValueSPtr( new ConcreteValue<int64_t>( DatumGetInt64(inDatum) )); case FLOAT4OID: return AbstractValueSPtr( new ConcreteValue<float>( DatumGetFloat4(inDatum) )); case FLOAT8OID: return AbstractValueSPtr( new ConcreteValue<double>( DatumGetFloat8(inDatum) )); } return AbstractValueSPtr(); }
/* * ex_avg() - an enhanced average calculation that takes two arguments; * number of rows in this group and partial sum of the value. * Then, it eventually generate mathmatically compatible average value. */ static int64 * check_int64_array(ArrayType *transarray, int n) { if (ARR_NDIM(transarray) != 1 || ARR_DIMS(transarray)[0] != n || ARR_HASNULL(transarray) || ARR_ELEMTYPE(transarray) != INT8OID) elog(ERROR, "Two elements int8 array is expected"); return (int64 *) ARR_DATA_PTR(transarray); }
Datum get_power_in_range(PG_FUNCTION_ARGS) { //the size of the array we are trying to transform int arraySize; int power; int32 duration; float startRange; float endRange; // a Datum for the constructred and deconstructed input arrays Datum *input_data; // the final result to return and the input to the function ArrayType *input; Oid input_type; //next 6 variables are inputted into get_typlenbyvalalign() and int fftw_export_wisdom_to_filename(const char *filename);are used for construct and deconstruct array //small int in postgreSQL is int16 int16 input_typelen; bool input_typbyval; char input_typalign; // get input row input = PG_GETARG_ARRAYTYPE_P(0); // get duration duration = PG_GETARG_INT32(1); // get ranges startRange = PG_GETARG_FLOAT8(2); endRange = PG_GETARG_FLOAT8(3); input_type = ARR_ELEMTYPE(input); //get needed variabels get_typlenbyvalalign(input_type, &input_typelen, &input_typbyval, &input_typalign); // deconstruct inupt array and save the array as Datum input_data deconstruct_array(input, input_type, input_typelen, input_typbyval, input_typalign, &input_data, NULL, &arraySize); // set the in variable to the array we got as input. // the real parts are from the input_data array // the imaginary part is set to 0 power = 0; for (int i = 0; i < arraySize; i++) { if(startRange < i/duration && i/duration <= endRange) { Complex *temp = (Complex*) DatumGetPointer(input_data[i]); power += temp->x*temp->x + temp->y*temp->y; } } // free memory pfree(input_data); // return result PG_RETURN_INT32(power); }
Datum welle_count( PG_FUNCTION_ARGS ) { if( PG_ARGISNULL( 0 ) ) { PG_RETURN_NULL(); } ArrayType * input; input = PG_GETARG_ARRAYTYPE_P( 0 ); Datum * i_data; Oid i_eltype; i_eltype = ARR_ELEMTYPE( input ); int16 i_typlen; bool i_typbyval; char i_typalign; get_typlenbyvalalign( i_eltype, &i_typlen, &i_typbyval, &i_typalign ); bool * nulls; int n; deconstruct_array( input, i_eltype, i_typlen, i_typbyval, i_typalign, &i_data, &nulls, &n ); switch( i_eltype ) { case INT4OID: PG_RETURN_POINTER( adeven_count_int_array( i_data, n, nulls ) ); break; case TEXTOID: PG_RETURN_POINTER( adeven_count_text_array( i_data, n, nulls ) ); break; default: elog( ERROR, "INVALID input data type" ); break; } }
/* * fetch_array_arg_replace_nulls * * Fetch an array-valued argument; if it's null, construct an empty array * value of the proper data type. Also cache basic element type information * in fn_extra. */ static ArrayType * fetch_array_arg_replace_nulls(FunctionCallInfo fcinfo, int argno) { ArrayType *v; Oid element_type; ArrayMetaState *my_extra; /* First collect the array value */ if (!PG_ARGISNULL(argno)) { v = PG_GETARG_ARRAYTYPE_P(argno); element_type = ARR_ELEMTYPE(v); } else { /* We have to look up the array type and element type */ Oid arr_typeid = get_fn_expr_argtype(fcinfo->flinfo, argno); if (!OidIsValid(arr_typeid)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("could not determine input data type"))); element_type = get_element_type(arr_typeid); if (!OidIsValid(element_type)) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("input data type is not an array"))); v = construct_empty_array(element_type); } /* Now cache required info, which might change from call to call */ my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; if (my_extra == NULL) { my_extra = (ArrayMetaState *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(ArrayMetaState)); my_extra->element_type = InvalidOid; fcinfo->flinfo->fn_extra = my_extra; } if (my_extra->element_type != element_type) { get_typlenbyvalalign(element_type, &my_extra->typlen, &my_extra->typbyval, &my_extra->typalign); my_extra->element_type = element_type; } return v; }
/* * anyarray_out - output routine for pseudo-type ANYARRAY. * * We may as well allow this, since array_out will in fact work. * XCP needs to send from data nodes to coordinator values of that type. * To be able to restore values at the destination node we need to know * actual element type. */ Datum anyarray_out(PG_FUNCTION_ARGS) { #ifdef XCP /* * Output prefix: (type_namespace_name.typename) to look up actual element * type at the destination node then output in usual format for array */ ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); Oid element_type = ARR_ELEMTYPE(v); Form_pg_type typeForm; HeapTuple typeTuple; char *typname, *typnspname; /* two identifiers, parenthesis, dot and trailing \0 */ char prefix[2*NAMEDATALEN+4], *retval, *newval; int prefixlen, retvallen; Datum array_out_result; MemoryContext save_context; save_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt); /* Figure out type name and type namespace */ typeTuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(element_type), 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "cache lookup failed for type %u", element_type); typeForm = (Form_pg_type) GETSTRUCT(typeTuple); typname = NameStr(typeForm->typname); typnspname = get_namespace_name(typeForm->typnamespace); sprintf(prefix, "(%s.%s)", typnspname, typname); ReleaseSysCache(typeTuple); MemoryContextSwitchTo(save_context); /* Get standard output and make up prefixed result */ array_out_result = array_out(fcinfo); retval = DatumGetCString(array_out_result); prefixlen = strlen(prefix); retvallen = strlen(retval); newval = (char *) palloc(prefixlen + retvallen + 1); strcpy(newval, prefix); strcpy(newval + prefixlen, retval); pfree(retval); PG_RETURN_CSTRING(newval); #else return array_out(fcinfo); #endif }
Datum find_peak_power(PG_FUNCTION_ARGS) { //the size of the array we are trying to transform int arraySize; int peak; // a Datum for the constructred and deconstructed input arrays Datum *input_data; // the final result to return and the input to the function ArrayType *input; Oid input_type; //next 6 variables are inputted into get_typlenbyvalalign() and are used for construct and deconstruct array //small int in postgreSQL is int16 int16 input_typelen; bool input_typbyval; char input_typalign; // get input row input = PG_GETARG_ARRAYTYPE_P(0); // get input array element type input_type = ARR_ELEMTYPE(input); //get needed variabels get_typlenbyvalalign(input_type, &input_typelen, &input_typbyval, &input_typalign); // deconstruct inupt array and save the array as Datum input_data deconstruct_array(input, input_type, input_typelen, input_typbyval, input_typalign, &input_data, NULL, &arraySize); // set the in variable to the array we got as input. // the real parts are from the input_data array // the imaginary part is set to 0 peak = 0; for (int i = 0; i < arraySize; i++) { Complex *temp = (Complex*) DatumGetPointer(input_data[i]); int tempValue = temp->x*temp->x + temp->y*temp->y; if(i == 0) { peak = tempValue; } else { if(tempValue > peak){ peak = tempValue; } } } // free memory pfree(input_data); // return result PG_RETURN_INT32(peak); }
/* * Transform a relation options list (list of DefElem) into the text array * format that is kept in pg_class.reloptions. * * This is used for three cases: CREATE TABLE/INDEX, ALTER TABLE SET, and * ALTER TABLE RESET. In the ALTER cases, oldOptions is the existing * reloptions value (possibly NULL), and we replace or remove entries * as needed. * * If ignoreOids is true, then we should ignore any occurrence of "oids" * in the list (it will be or has been handled by interpretOidsOption()). * * Note that this is not responsible for determining whether the options * are valid. * * Both oldOptions and the result are text arrays (or NULL for "default"), * but we declare them as Datums to avoid including array.h in reloptions.h. */ Datum transformRelOptions(Datum oldOptions, List *defList, bool ignoreOids, bool isReset) { Datum result; ArrayBuildState *astate; ListCell *cell; /* no change if empty list */ if (defList == NIL) return oldOptions; /* We build new array using accumArrayResult */ astate = NULL; /* Copy any oldOptions that aren't to be replaced */ if (DatumGetPointer(oldOptions) != 0) { ArrayType *array = DatumGetArrayTypeP(oldOptions); Datum *oldoptions; int noldoptions; int i; Assert(ARR_ELEMTYPE(array) == TEXTOID); deconstruct_array(array, TEXTOID, -1, false, 'i', &oldoptions, NULL, &noldoptions); for (i = 0; i < noldoptions; i++) { text *oldoption = DatumGetTextP(oldoptions[i]); char *text_str = VARDATA(oldoption); int text_len = VARSIZE(oldoption) - VARHDRSZ; /* Search for a match in defList */ foreach(cell, defList) { DefElem *def = lfirst(cell); int kw_len = strlen(def->defname); if (text_len > kw_len && text_str[kw_len] == '=' && pg_strncasecmp(text_str, def->defname, kw_len) == 0) break; } if (!cell) { /* No match, so keep old option */ astate = accumArrayResult(astate, oldoptions[i], false, TEXTOID, CurrentMemoryContext); } }
/* * UpdateCmsTopn is a helper function to add new item to CmsTopn structure. It * adds the item to the sketch, calculates its frequency, and updates the top-n * array. Finally it forms new CmsTopn from updated sketch and updated top-n array. */ static CmsTopn * UpdateCmsTopn(CmsTopn *currentCmsTopn, Datum newItem, TypeCacheEntry *newItemTypeCacheEntry) { CmsTopn *updatedCmsTopn = NULL; ArrayType *currentTopnArray = NULL; ArrayType *updatedTopnArray = NULL; Datum detoastedItem = 0; Oid newItemType = newItemTypeCacheEntry->type_id; Oid currentItemType = InvalidOid; Frequency newItemFrequency = 0; bool topnArrayUpdated = false; Size currentTopnArrayLength = 0; currentTopnArray = TopnArray(currentCmsTopn); currentTopnArrayLength = ARR_DIMS(currentTopnArray)[0]; currentItemType = ARR_ELEMTYPE(currentTopnArray); if (currentTopnArrayLength != 0 && currentItemType != newItemType) { ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("not proper type for this cms_topn"))); } /* if datum is toasted, detoast it */ if (newItemTypeCacheEntry->typlen == -1) { detoastedItem = PointerGetDatum(PG_DETOAST_DATUM(newItem)); } else { detoastedItem = newItem; } newItemFrequency = UpdateSketchInPlace(currentCmsTopn, detoastedItem, newItemTypeCacheEntry); updatedTopnArray = UpdateTopnArray(currentCmsTopn, detoastedItem, newItemTypeCacheEntry, newItemFrequency, &topnArrayUpdated); /* we only form a new CmsTopn only if top-n array is updated */ if (topnArrayUpdated) { updatedCmsTopn = FormCmsTopn(currentCmsTopn, updatedTopnArray); } else { updatedCmsTopn = currentCmsTopn; } return updatedCmsTopn; }
/* * Turn an array into JSON. */ static void array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds) { ArrayType *v = DatumGetArrayTypeP(array); Oid element_type = ARR_ELEMTYPE(v); int *dim; int ndim; int nitems; int count = 0; Datum *elements; bool *nulls; int16 typlen; bool typbyval; char typalign, typdelim; Oid typioparam; Oid typoutputfunc; TYPCATEGORY tcategory; ndim = ARR_NDIM(v); dim = ARR_DIMS(v); nitems = ArrayGetNItems(ndim, dim); if (nitems <= 0) { appendStringInfoString(result,"[]"); return; } get_type_io_data(element_type, IOFunc_output, &typlen, &typbyval, &typalign, &typdelim, &typioparam, &typoutputfunc); deconstruct_array(v, element_type, typlen, typbyval, typalign, &elements, &nulls, &nitems); if (element_type == RECORDOID) tcategory = TYPCATEGORY_COMPOSITE; else if (element_type == JSONOID) tcategory = TYPCATEGORY_JSON; else tcategory = TypeCategory(element_type); array_dim_to_json(result, 0, ndim, dim, elements, &count, tcategory, typoutputfunc, use_line_feeds); pfree(elements); pfree(nulls); }
static float8 * check_float8_array(ArrayType *transarray, const char *caller) { /* * We expect the input to be a 3-element float array; verify that. We * don't need to use deconstruct_array() since the array data is just * going to look like a C array of 3 float8 values. */ if (ARR_NDIM(transarray) != 1 || ARR_DIMS(transarray)[0] != 3 || ARR_ELEMTYPE(transarray) != FLOAT8OID) elog(ERROR, "%s: expected 3-element float8 array", caller); return (float8 *) ARR_DATA_PTR(transarray); }
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); }
/* logic copied from utils/adt/float.c */ static inline float8 * check_float8_array(ArrayType *transarray, int nitems) { /* * We expect the input to be an N-element float array; verify that. We * don't need to use deconstruct_array() since the array data is just * going to look like a C array of N float8 values. */ if (ARR_NDIM(transarray) != 1 || ARR_DIMS(transarray)[0] != nitems || ARR_HASNULL(transarray) || ARR_ELEMTYPE(transarray) != FLOAT8OID) elog(ERROR, "%d-elements float8 array is expected", nitems); return (float8 *) ARR_DATA_PTR(transarray); }
static inline void get_svec_array_elms(ArrayType *inArrayType, Datum **outSvecArr, int *outLen) { deconstruct_array(inArrayType, /* array */ ARR_ELEMTYPE(inArrayType), /* elmtype */ -1, /* elmlen */ false, /* elmbyval */ 'd', /* elmalign */ outSvecArr, /* elemsp */ NULL, /* nullsp -- pass NULL, because we don't support NULLs */ outLen); /* nelemsp */ }