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); }
/* * Types are always allocated in global context. */ Type TypeClass_allocInstance2(TypeClass cls, Oid typeId, Form_pg_type pgType) { Type t = (Type)PgObjectClass_allocInstance((PgObjectClass)(cls), TopMemoryContext); t->typeId = typeId; t->arrayType = 0; t->elementType = 0; t->objectType = 0; t->inCoercions = 0; t->outCoercions = 0; if(pgType != 0) { t->length = pgType->typlen; t->byValue = pgType->typbyval; t->align = pgType->typalign; } else if(typeId != InvalidOid) { get_typlenbyvalalign(typeId, &t->length, &t->byValue, &t->align); } else { t->length = 0; t->byValue = true; t->align = 'i'; } return t; }
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"); }
/* * 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 */ }
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); } } }
/* * 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); }
static Datum build_array(element_set_t * eset, Oid element_type) { Datum * array_of_datums; int i; int16 typlen; bool typbyval; char typalign; /* do the compaction */ compact_set(eset, false); #if DEBUG_PROFILE print_set_stats(eset); #endif /* get detailed type information on the element type */ get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign); /* Copy data from compact array to array of Datums * A bit suboptimal way, spends excessive memory */ array_of_datums = palloc0(eset->nsorted * sizeof(Datum)); for (i = 0; i < eset->nsorted; i++) memcpy(array_of_datums + i, eset->data + (eset->item_size * i), eset->item_size); /* build and return the array */ PG_RETURN_DATUM(PointerGetDatum(construct_array( array_of_datums, eset->nsorted, element_type, typlen, typbyval, typalign ))); }
Datum postal_normalize(PG_FUNCTION_ARGS) { text *address = PG_GETARG_TEXT_P(0); size_t arr_nelems, i; libpostal_normalize_options_t options = libpostal_get_default_options(); char **expansions = libpostal_expand_address(text_to_cstring(address), options, &arr_nelems); ArrayType *arr; Datum *arr_elems = palloc(sizeof(Datum) * arr_nelems); Oid elem_type = TEXTOID; int16 elem_len; char elem_byval; char elem_align; get_typlenbyvalalign(elem_type, &elem_len, &elem_byval, &elem_align); for (i = 0; i < arr_nelems; i++) { arr_elems[i] = PointerGetDatum(cstring_to_text(expansions[i])); } /* Array construction takes a full copy of the input */ arr = construct_array(arr_elems, arr_nelems, elem_type, elem_len, elem_byval, elem_align); /* Clean up unmanaged memory */ libpostal_expansion_array_destroy(expansions, arr_nelems); PG_RETURN_ARRAYTYPE_P(arr); }
/* * actually does the work for array(), and array_accum() if it is given a null * input array. * * numelems and elem_start allow the function to be shared given the differing * arguments accepted by array() and array_accum(). With array(), all function * arguments are used for array construction -- therefore elem_start is 0 and * numelems is the number of function arguments. With array_accum(), we are * always initializing the array with a single element given to us as argument * number 1 (i.e. the second argument). * */ static ArrayType * plr_array_create(FunctionCallInfo fcinfo, int numelems, int elem_start) { Oid funcid = fcinfo->flinfo->fn_oid; Datum *dvalues = (Datum *) palloc(numelems * sizeof(Datum)); int16 typlen; bool typbyval; Oid typinput; Oid element_type; char typalign; int i; HeapTuple tp; Oid functypeid; Oid *funcargtypes; ArrayType *result; if (numelems == 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("at least one value required to construct an array"))); /* * Get the type metadata for the array return type and its elements */ tp = SearchSysCache(PROCOID, ObjectIdGetDatum(funcid), 0, 0, 0); if (!HeapTupleIsValid(tp)) /* internal error */ elog(ERROR, "function OID %u does not exist", funcid); functypeid = ((Form_pg_proc) GETSTRUCT(tp))->prorettype; getTypeInputInfo(functypeid, &typinput, &element_type); get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign); funcargtypes = FUNCARGTYPES(tp); /* * the first function argument(s) may not be one of our array elements, * but the caller is responsible to ensure we get nothing but array * elements once they start coming */ for (i = elem_start; i < elem_start + numelems; i++) if (funcargtypes[i] != element_type) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("argument %d datatype not " \ "compatible with return data type", i + 1))); ReleaseSysCache(tp); for (i = 0; i < numelems; i++) dvalues[i] = PG_GETARG_DATUM(elem_start + i); result = construct_array(dvalues, numelems, element_type, typlen, typbyval, typalign); return result; }
/* * 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 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); }
/* * used by text_to_array() in varlena.c */ array_s *create_singleton_array(struct fc_info* fcinfo, oid_t element_type, datum_t element, bool isNull, int ndims) { datum_t dvalues[1]; bool nulls[1]; int16 typlen; bool typbyval; char typalign; int dims[MAXDIM]; int lbs[MAXDIM]; int i; array_meta_s *my_extra; if (ndims < 1) ereport(ERROR, ( errcode(E_INVALID_PARAMETER_VALUE), errmsg("invalid number of dimensions: %d", ndims))); if (ndims > MAXDIM) ereport(ERROR, ( errcode(E_PROGRAM_LIMIT_EXCEEDED), errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)", ndims, MAXDIM))); dvalues[0] = element; nulls[0] = isNull; for (i = 0; i < ndims; i++) { dims[i] = 1; lbs[i] = 1; } /* * 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 = (array_meta_s *) fcinfo->flinfo->fn_extra; if (my_extra == NULL) { fcinfo->flinfo->fn_extra = mctx_alloc(fcinfo->flinfo->fn_mcxt, sizeof(array_meta_s)); my_extra = (array_meta_s *) 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; return construct_md_array(dvalues, nulls, ndims, dims, lbs, element_type, typlen, typbyval, typalign); }
/* * 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); }
Datum count_distinct_append(PG_FUNCTION_ARGS) { element_set_t *eset; /* info for anyelement */ Oid element_type = get_fn_expr_argtype(fcinfo->flinfo, 1); Datum element = PG_GETARG_DATUM(1); /* memory contexts */ MemoryContext oldcontext; MemoryContext aggcontext; /* * If the new value is NULL, we simply return the current aggregate state * (it might be NULL, so check it). */ if (PG_ARGISNULL(1) && PG_ARGISNULL(0)) PG_RETURN_NULL(); else if (PG_ARGISNULL(1)) PG_RETURN_DATUM(PG_GETARG_DATUM(0)); /* from now on we know the new value is not NULL */ /* switch to the per-group hash-table memory context */ GET_AGG_CONTEXT("count_distinct_append", fcinfo, aggcontext); oldcontext = MemoryContextSwitchTo(aggcontext); /* init the hash table, if needed */ if (PG_ARGISNULL(0)) { int16 typlen; bool typbyval; char typalign; /* get type information for the second parameter (anyelement item) */ get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign); /* we can't handle varlena types yet or values passed by reference */ if ((typlen < 0) || (! typbyval)) elog(ERROR, "count_distinct handles only fixed-length types passed by value"); eset = init_set(typlen, typalign, aggcontext); } else eset = (element_set_t *)PG_GETARG_POINTER(0); /* add the value into the set */ add_element(eset, (char*)&element); MemoryContextSwitchTo(oldcontext); PG_RETURN_POINTER(eset); }
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; }
Datum dbms_output_get_lines(PG_FUNCTION_ARGS) { TupleDesc tupdesc; Datum result; HeapTuple tuple; Datum values[2]; bool nulls[2] = { false, false }; text *line; int32 max_lines = PG_GETARG_INT32(0); int32 n; ArrayBuildState *astate = NULL; /* Build a tuple descriptor for our result type */ if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) elog(ERROR, "return type must be a row type"); for (n = 0; n < max_lines && (line = dbms_output_next()) != NULL; n++) { astate = accumArrayResult(astate, PointerGetDatum(line), false, TEXTOID, CurrentMemoryContext); } /* 0: lines as text array */ if (n > 0) values[0] = makeArrayResult(astate, CurrentMemoryContext); else { int16 typlen; bool typbyval; char typalign; ArrayType *arr; get_typlenbyvalalign(TEXTOID, &typlen, &typbyval, &typalign); arr = construct_md_array( NULL, #if PG_VERSION_NUM >= 80200 NULL, #endif 0, NULL, NULL, TEXTOID, typlen, typbyval, typalign); values[0] = PointerGetDatum(arr); } /* 1: # of lines as integer */ values[1] = Int32GetDatum(n); tuple = heap_form_tuple(tupdesc, values, nulls); result = HeapTupleGetDatum(tuple); PG_RETURN_DATUM(result); }
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); }
static void initXNodeTypeInfo(Oid fnOid, int argNr, TypeInfo *ti) { HeapTuple tup; Form_pg_proc procStruct; tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fnOid)); Assert(HeapTupleIsValid(tup)); procStruct = (Form_pg_proc) GETSTRUCT(tup); ti->oid = procStruct->proargtypes.values[argNr]; ReleaseSysCache(tup); get_typlenbyvalalign(ti->oid, &ti->elmlen, &ti->elmbyval, &ti->elmalign); }
Datum adaptive_add_item_agg2(PG_FUNCTION_ARGS) { AdaptiveCounter acounter; /* info for anyelement */ Oid element_type = get_fn_expr_argtype(fcinfo->flinfo, 1); Datum element = PG_GETARG_DATUM(1); int16 typlen; bool typbyval; char typalign; /* is the counter created (if not, create it with default parameters) */ if (PG_ARGISNULL(0)) { acounter = ac_init(DEFAULT_ERROR, DEFAULT_NDISTINCT); } else { acounter = (AdaptiveCounter)PG_GETARG_BYTEA_P(0); } /* add the item to the estimator */ if (! PG_ARGISNULL(1)) { /* TODO The requests for type info shouldn't be a problem (thanks to lsyscache), * but if it turns out to have a noticeable impact it's possible to cache that * between the calls (in the estimator). */ /* get type information for the second parameter (anyelement item) */ get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign); /* it this a varlena type, passed by reference or by value ? */ if (typlen == -1) { /* varlena */ ac_add_item(acounter, VARDATA(element), VARSIZE(element) - VARHDRSZ); } else if (typbyval) { /* fixed-length, passed by value */ ac_add_item(acounter, (char*)&element, typlen); } else { /* fixed-length, passed by reference */ ac_add_item(acounter, (char*)element, typlen); } } /* return the updated bytea */ PG_RETURN_BYTEA_P(acounter); }
Datum anyold_transfn(PG_FUNCTION_ARGS) { Oid type; Datum state; MemoryContext aggcontext, oldcontext; int16 typlen; bool typbyval; char typalign; if (!AggCheckCallContext(fcinfo, &aggcontext)) { /* cannot be called directly because of internal-type argument */ elog(ERROR, "anyold_transfn called in non-aggregate context"); } if (PG_ARGISNULL(0)) { if (PG_ARGISNULL(1)) PG_RETURN_NULL(); /* First non-null value --- initialize */ oldcontext = MemoryContextSwitchTo(aggcontext); type = get_fn_expr_argtype(fcinfo->flinfo, 1); if (type == InvalidOid) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("could not determine input data type"))); get_typlenbyvalalign(type, &typlen, &typbyval, &typalign); /* Copy initial value */ if (typlen == -1) state = PointerGetDatum(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1))); else state = datumCopy(PG_GETARG_DATUM(1), typbyval, typlen); MemoryContextSwitchTo(oldcontext); } else { state = PG_GETARG_DATUM(0); } PG_RETURN_DATUM(state); }
Datum probabilistic_add_item_agg2(PG_FUNCTION_ARGS) { ProbabilisticCounter pcounter; /* info for anyelement */ Oid element_type = get_fn_expr_argtype(fcinfo->flinfo, 1); Datum element = PG_GETARG_DATUM(1); int16 typlen; bool typbyval; char typalign; /* create a new estimator (with requested error rate) or reuse the existing one */ if (PG_ARGISNULL(0)) { pcounter = pc_create(DEFAULT_NBYTES, DEFAULT_NSALTS); } else { /* existing estimator */ pcounter = (ProbabilisticCounter)PG_GETARG_BYTEA_P(0); } /* add the item to the estimator (skip NULLs) */ if (! PG_ARGISNULL(1)) { /* TODO The requests for type info shouldn't be a problem (thanks to lsyscache), * but if it turns out to have a noticeable impact it's possible to cache that * between the calls (in the estimator). */ /* get type information for the second parameter (anyelement item) */ get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign); /* it this a varlena type, passed by reference or by value ? */ if (typlen == -1) { /* varlena */ pc_add_element(pcounter, VARDATA(element), VARSIZE(element) - VARHDRSZ); } else if (typbyval) { /* fixed-length, passed by value */ pc_add_element(pcounter, (char*)&element, typlen); } else { /* fixed-length, passed by reference */ pc_add_element(pcounter, (char*)element, typlen); } } /* return the updated bytea */ PG_RETURN_BYTEA_P(pcounter); }
Datum probabilistic_add_item(PG_FUNCTION_ARGS) { ProbabilisticCounter pcounter; /* requires the estimator to be already created */ if (PG_ARGISNULL(0)) elog(ERROR, "probabilistic counter must not be NULL"); /* if the element is not NULL, add it to the estimator (i.e. skip NULLs) */ if (! PG_ARGISNULL(1)) { Oid element_type = get_fn_expr_argtype(fcinfo->flinfo, 1); Datum element = PG_GETARG_DATUM(1); int16 typlen; bool typbyval; char typalign; /* estimator (we know it's not a NULL value) */ pcounter = (ProbabilisticCounter)PG_GETARG_BYTEA_P(0); /* TODO The requests for type info shouldn't be a problem (thanks to lsyscache), * but if it turns out to have a noticeable impact it's possible to cache that * between the calls (in the estimator). */ /* get type information for the second parameter (anyelement item) */ get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign); /* it this a varlena type, passed by reference or by value ? */ if (typlen == -1) { /* varlena */ pc_add_element(pcounter, VARDATA(element), VARSIZE(element) - VARHDRSZ); } else if (typbyval) { /* fixed-length, passed by value */ pc_add_element(pcounter, (char*)&element, typlen); } else { /* fixed-length, passed by reference */ pc_add_element(pcounter, (char*)element, typlen); } } PG_RETURN_VOID(); }
/* * 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); }
/* * Turn an array into JSON. */ static void array_to_jsonb_internal(Datum array, JsonbInState *result) { 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; JsonbTypeCategory tcategory; Oid outfuncoid; ndim = ARR_NDIM(v); dim = ARR_DIMS(v); nitems = ArrayGetNItems(ndim, dim); if (nitems <= 0) { result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL); result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL); return; } get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign); jsonb_categorize_type(element_type, &tcategory, &outfuncoid); deconstruct_array(v, element_type, typlen, typbyval, typalign, &elements, &nulls, &nitems); array_dim_to_jsonb(result, 0, ndim, dim, elements, nulls, &count, tcategory, outfuncoid); pfree(elements); pfree(nulls); }
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); }
ArrayType *build_array(q3c_coord_t ra, q3c_coord_t dec) { Datum *data; int16 typlen; bool typbyval; char typalign; int nelems; ArrayType *result; nelems = 2; data = ( Datum *) palloc(sizeof(Datum) * nelems); data[0] = Float8GetDatum (ra); data[1] = Float8GetDatum (dec); /* get required info about the element type */ get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign); /* now build the array */ result = construct_array(data, nelems, FLOAT8OID, typlen, typbyval, typalign); return result; }
/* * ExecIndexEvalArrayKeys * Evaluate any array key values, and set up to iterate through arrays. * * Returns TRUE if there are array elements to consider; FALSE means there * is at least one null or empty array, so no match is possible. On TRUE * result, the scankeys are initialized with the first elements of the arrays. */ bool ExecIndexEvalArrayKeys(ExprContext *econtext, IndexArrayKeyInfo *arrayKeys, int numArrayKeys) { bool result = true; int j; MemoryContext oldContext; /* We want to keep the arrays in per-tuple memory */ oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); for (j = 0; j < numArrayKeys; j++) { ScanKey scan_key = arrayKeys[j].scan_key; ExprState *array_expr = arrayKeys[j].array_expr; Datum arraydatum; bool isNull; ArrayType *arrayval; int16 elmlen; bool elmbyval; char elmalign; int num_elems; Datum *elem_values; bool *elem_nulls; /* * Compute and deconstruct the array expression. (Notes in * ExecIndexEvalRuntimeKeys() apply here too.) */ arraydatum = ExecEvalExpr(array_expr, econtext, &isNull, NULL); if (isNull) { result = false; break; /* no point in evaluating more */ } arrayval = DatumGetArrayTypeP(arraydatum); /* We could cache this data, but not clear it's worth it */ get_typlenbyvalalign(ARR_ELEMTYPE(arrayval), &elmlen, &elmbyval, &elmalign); deconstruct_array(arrayval, ARR_ELEMTYPE(arrayval), elmlen, elmbyval, elmalign, &elem_values, &elem_nulls, &num_elems); if (num_elems <= 0) { result = false; break; /* no point in evaluating more */ } /* * Note: we expect the previous array data, if any, to be * automatically freed by resetting the per-tuple context; hence no * pfree's here. */ arrayKeys[j].elem_values = elem_values; arrayKeys[j].elem_nulls = elem_nulls; arrayKeys[j].num_elems = num_elems; scan_key->sk_argument = elem_values[0]; if (elem_nulls[0]) scan_key->sk_flags |= SK_ISNULL; else scan_key->sk_flags &= ~SK_ISNULL; arrayKeys[j].next_elem = 1; } MemoryContextSwitchTo(oldContext); return result; }
/* * used by text_to_array() in varlena.c */ ArrayType * create_singleton_array(FunctionCallInfo fcinfo, Oid element_type, Datum element, int ndims) { Datum dvalues[1]; int16 typlen; bool typbyval; char typalign; int dims[MAXDIM]; int lbs[MAXDIM]; int i; ArrayMetaState *my_extra; if (ndims < 1) 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))); dvalues[0] = element; for (i = 0; i < ndims; i++) { dims[i] = 1; lbs[i] = 1; } /* * 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; return construct_md_array(dvalues, NULL, ndims, dims, lbs, element_type, typlen, typbyval, typalign); }