/* * 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); }
Datum plr_array_accum(PG_FUNCTION_ARGS) { Datum v; Datum newelem; ArrayType *result; /* return NULL if both arguments are NULL */ if (PG_ARGISNULL(0) && PG_ARGISNULL(1)) PG_RETURN_NULL(); /* create a new array from the second argument if first is NULL */ if (PG_ARGISNULL(0)) PG_RETURN_ARRAYTYPE_P(plr_array_create(fcinfo, 1, 1)); /* return the first argument if the second is NULL */ if (PG_ARGISNULL(1)) PG_RETURN_ARRAYTYPE_P(PG_GETARG_ARRAYTYPE_P_COPY(0)); v = PG_GETARG_DATUM(0); newelem = PG_GETARG_DATUM(1); result = DatumGetArrayTypeP(DirectFunctionCall2(plr_array_push, v, newelem)); PG_RETURN_ARRAYTYPE_P(result); }
Datum sort(PG_FUNCTION_ARGS) { ArrayType *a = (ArrayType *) PG_GETARG_ARRAYTYPE_P_COPY(0); text *dirstr = (fcinfo->nargs == 2) ? PG_GETARG_TEXT_P(1) : NULL; int32 dc = (dirstr) ? VARSIZE(dirstr) - VARHDRSZ : 0; char *d = (dirstr) ? VARDATA(dirstr) : NULL; int dir = -1; CHECKARRVALID(a); if (ARRNELEMS(a) < 2) PG_RETURN_POINTER(a); if (dirstr == NULL || (dc == 3 && (d[0] == 'A' || d[0] == 'a') && (d[1] == 'S' || d[1] == 's') && (d[2] == 'C' || d[2] == 'c'))) dir = 1; else if (dc == 4 && (d[0] == 'D' || d[0] == 'd') && (d[1] == 'E' || d[1] == 'e') && (d[2] == 'S' || d[2] == 's') && (d[3] == 'C' || d[3] == 'c')) dir = 0; if (dir == -1) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("second parameter must be \"ASC\" or \"DESC\""))); QSORT(a, dir); PG_RETURN_POINTER(a); }
Datum pgstrom_final_avg_float8_accum(PG_FUNCTION_ARGS) { MemoryContext aggcxt; MemoryContext oldcxt; ArrayType *xarray; ArrayType *yarray; float8 *x, *y; if (!AggCheckCallContext(fcinfo, &aggcxt)) elog(ERROR, "aggregate function called in non-aggregate context"); if (PG_ARGISNULL(1)) elog(ERROR, "Null state was supplied"); if (PG_ARGISNULL(0)) { oldcxt = MemoryContextSwitchTo(aggcxt); xarray = PG_GETARG_ARRAYTYPE_P_COPY(1); MemoryContextSwitchTo(oldcxt); } else { xarray = PG_GETARG_ARRAYTYPE_P(0); yarray = PG_GETARG_ARRAYTYPE_P(1); x = (float8 *)ARR_DATA_PTR(xarray); y = (float8 *)ARR_DATA_PTR(yarray); x[0] += y[0]; x[1] += y[1]; } PG_RETURN_POINTER(xarray); }
Datum intarray_del_elem(PG_FUNCTION_ARGS) { ArrayType *a = (ArrayType *) PG_GETARG_ARRAYTYPE_P_COPY(0); int32 elem = PG_GETARG_INT32(1); int32 c; int32 *aa; int32 n = 0, i; CHECKARRVALID(a); if (!ARRISEMPTY(a)) { c = ARRNELEMS(a); aa = ARRPTR(a); for (i = 0; i < c; i++) { if (aa[i] != elem) { if (i > n) aa[n++] = aa[i]; else n++; } } a = resize_intArrayType(a, n); } PG_RETURN_POINTER(a); }
/* * 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 _int_contains(PG_FUNCTION_ARGS) { /* Force copy so we can modify the arrays in-place */ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0); ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1); bool res; CHECKARRVALID(a); CHECKARRVALID(b); PREPAREARR(a); PREPAREARR(b); res = inner_int_contains(a, b); pfree(a); pfree(b); PG_RETURN_BOOL(res); }
Datum intset_subtract(PG_FUNCTION_ARGS) { ArrayType *a = (ArrayType *) PG_GETARG_ARRAYTYPE_P_COPY(0); ArrayType *b = (ArrayType *) PG_GETARG_ARRAYTYPE_P_COPY(1); ArrayType *result; int32 ca; int32 cb; int32 *aa, *bb, *r; int32 n = 0, i = 0, k = 0; CHECKARRVALID(a); CHECKARRVALID(b); QSORT(a, 1); a = _int_unique(a); ca = ARRNELEMS(a); QSORT(b, 1); b = _int_unique(b); cb = ARRNELEMS(b); result = new_intArrayType(ca); aa = ARRPTR(a); bb = ARRPTR(b); r = ARRPTR(result); while (i < ca) { if (k == cb || aa[i] < bb[k]) r[n++] = aa[i++]; else if (aa[i] == bb[k]) { i++; k++; } else k++; } result = resize_intArrayType(result, n); pfree(a); pfree(b); PG_RETURN_POINTER(result); }
Datum sort_desc(PG_FUNCTION_ARGS) { ArrayType *a = (ArrayType *) PG_GETARG_ARRAYTYPE_P_COPY(0); CHECKARRVALID(a); QSORT(a, 0); PG_RETURN_POINTER(a); }
Datum _int_same(PG_FUNCTION_ARGS) { ArrayType *a = (ArrayType *) PG_GETARG_ARRAYTYPE_P_COPY(0); ArrayType *b = (ArrayType *) PG_GETARG_ARRAYTYPE_P_COPY(1); int na, nb; int n; int *da, *db; bool result; CHECKARRVALID(a); CHECKARRVALID(b); na = ARRNELEMS(a); nb = ARRNELEMS(b); da = ARRPTR(a); db = ARRPTR(b); result = FALSE; if (na == nb) { SORT(a); SORT(b); result = TRUE; for (n = 0; n < na; n++) { if (da[n] != db[n]) { result = FALSE; break; } } } pfree(a); pfree(b); PG_RETURN_BOOL(result); }
Datum uniq(PG_FUNCTION_ARGS) { ArrayType *a = (ArrayType *) PG_GETARG_ARRAYTYPE_P_COPY(0); CHECKARRVALID(a); if (ARRNELEMS(a) < 2) PG_RETURN_POINTER(a); a = _int_unique(a); PG_RETURN_POINTER(a); }
Datum _int_inter(PG_FUNCTION_ARGS) { ArrayType *a = (ArrayType *) PG_GETARG_ARRAYTYPE_P_COPY(0); ArrayType *b = (ArrayType *) PG_GETARG_ARRAYTYPE_P_COPY(1); ArrayType *result; CHECKARRVALID(a); CHECKARRVALID(b); SORT(a); SORT(b); result = inner_int_inter(a, b); pfree(a); pfree(b); PG_RETURN_POINTER(result); }
/* _int_overlap -- does a overlap b? */ Datum _int_overlap(PG_FUNCTION_ARGS) { ArrayType *a = (ArrayType *) PG_GETARG_ARRAYTYPE_P_COPY(0); ArrayType *b = (ArrayType *) PG_GETARG_ARRAYTYPE_P_COPY(1); bool result; CHECKARRVALID(a); CHECKARRVALID(b); if (ARRISEMPTY(a) || ARRISEMPTY(b)) return FALSE; SORT(a); SORT(b); result = inner_int_overlap(a, b); pfree(a); pfree(b); PG_RETURN_BOOL(result); }
Datum pgstrom_final_avg_numeric_accum(PG_FUNCTION_ARGS) { MemoryContext aggcxt; MemoryContext oldcxt; ArrayType *xarray; ArrayType *yarray; Datum x0, x1; Datum y0, y1; Datum items[2]; bool isnull[4]; if (!AggCheckCallContext(fcinfo, &aggcxt)) elog(ERROR, "aggregate function called in non-aggregate context"); if (PG_ARGISNULL(1)) elog(ERROR, "Null state was supplied"); if (PG_ARGISNULL(0)) { oldcxt = MemoryContextSwitchTo(aggcxt); xarray = PG_GETARG_ARRAYTYPE_P_COPY(1); MemoryContextSwitchTo(oldcxt); } else { xarray = PG_GETARG_ARRAYTYPE_P(0); yarray = PG_GETARG_ARRAYTYPE_P(1); x0 = numeric_array_ref(xarray, 1, &isnull[0]); x1 = numeric_array_ref(xarray, 2, &isnull[1]); y0 = numeric_array_ref(yarray, 1, &isnull[2]); y1 = numeric_array_ref(yarray, 2, &isnull[3]); if (isnull[0] || isnull[1] || isnull[2] || isnull[3]) elog(ERROR, "unexpected internal state"); items[0] = DirectFunctionCall2(numeric_add, x0, y0); items[1] = DirectFunctionCall2(numeric_add, x1, y1); oldcxt = MemoryContextSwitchTo(aggcxt); xarray = construct_array(items, 2, NUMERICOID, -1, false, 'i'); MemoryContextSwitchTo(oldcxt); } PG_RETURN_POINTER(xarray); }
/* * 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); }
Datum boolop(PG_FUNCTION_ARGS) { ArrayType *val = PG_GETARG_ARRAYTYPE_P_COPY(0); QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(1); CHKVAL chkval; bool result; CHECKARRVALID(val); PREPAREARR(val); chkval.arrb = ARRPTR(val); chkval.arre = chkval.arrb + ARRNELEMS(val); result = execute(GETQUERY(query) + query->size - 1, &chkval, true, checkcondition_arr); pfree(val); PG_FREE_IF_COPY(query, 1); PG_RETURN_BOOL(result); }
Datum internal_kmeans_agg_centroid_merge(PG_FUNCTION_ARGS) { /* This function is declared as strict. No checking null here. */ ArrayType *array = NULL; ArrayType *array2 = NULL; if (fcinfo->context && IsA(fcinfo->context, AggState)) array = PG_GETARG_ARRAYTYPE_P(0); else array = PG_GETARG_ARRAYTYPE_P_COPY(0); int array_dim = ARR_NDIM(array); int *p_array_dim = ARR_DIMS(array); int array_length = ArrayGetNItems(array_dim, p_array_dim); array2 = PG_GETARG_ARRAYTYPE_P(1); array_dim = ARR_NDIM(array2); p_array_dim = ARR_DIMS(array2); int array2_length = ArrayGetNItems(array_dim, p_array_dim); if (array_length != array2_length) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("function \"%s\", Inconsistent array length. " "first: %d, second:%d", format_procedure(fcinfo->flinfo->fn_oid), array_length, array2_length))); } float8* c_array = (float8 *)ARR_DATA_PTR(array); float8* c_array2 = (float8 *)ARR_DATA_PTR(array2); for(int i=0; i<array_length; i++) { c_array[i]+= c_array2[i]; } PG_RETURN_ARRAYTYPE_P(array); }
/* * The step function for aggregating the class counts while doing Reduce Error Pruning (REP). * * Parameters: * class_count_array The array used to store the accumulated information. * [0]: the total number of mis-classified cases * [i]: the number of cases belonging to the ith class * classified_class The predicted class based on our trained DT model. * original_class The real class value provided in the validation set. * max_num_of_classes The total number of distinct class values. * Return: * An updated state array. */ Datum rep_aggr_class_count_sfunc(PG_FUNCTION_ARGS) { ArrayType *class_count_array = NULL; int array_dim = 0; int *p_array_dim = NULL; int array_length = 0; int64 *class_count_data = NULL; int classified_class = PG_GETARG_INT32(1); int original_class = PG_GETARG_INT32(2); int max_num_of_classes = PG_GETARG_INT32(3); bool need_reconstruct_array = false; check_error_value ( max_num_of_classes >= 2, "invalid value: %d. The number of classes must be greater than or equal to 2", max_num_of_classes ); check_error_value ( original_class > 0 && original_class <= max_num_of_classes, "invalid real class value: %d. It must be in range from 1 to the number of classes", original_class ); check_error_value ( classified_class > 0 && classified_class <= max_num_of_classes, "invalid classified class value: %d. It must be in range from 1 to the number of classes", classified_class ); /* test if the first argument (class count array) is null */ if (PG_ARGISNULL(0)) { /* * We assume the maximum number of classes is limited (up to millions), * so that the allocated array won't break our memory limitation. */ class_count_data = palloc0(sizeof(int64) * (max_num_of_classes + 1)); array_length = max_num_of_classes + 1; need_reconstruct_array = true; } else { if (fcinfo->context && IsA(fcinfo->context, AggState)) class_count_array = PG_GETARG_ARRAYTYPE_P(0); else class_count_array = PG_GETARG_ARRAYTYPE_P_COPY(0); check_error ( class_count_array, "invalid aggregation state array" ); array_dim = ARR_NDIM(class_count_array); check_error_value ( array_dim == 1, "invalid array dimension: %d. The dimension of class count array must be equal to 1", array_dim ); p_array_dim = ARR_DIMS(class_count_array); array_length = ArrayGetNItems(array_dim,p_array_dim); class_count_data = (int64 *)ARR_DATA_PTR(class_count_array); check_error_value ( array_length == max_num_of_classes + 1, "invalid array length: %d. The length of class count array must be equal to the total number classes + 1", array_length ); } /* * If the condition is met, then the current record has been mis-classified. * Therefore, we will need to increase the first element. */ if(original_class != classified_class) ++class_count_data[0]; /* In any case, we will update the original class count */ ++class_count_data[original_class]; if( need_reconstruct_array ) { /* construct a new array to keep the aggr states. */ class_count_array = construct_array( (Datum *)class_count_data, array_length, INT8OID, sizeof(int64), true, 'd' ); } PG_RETURN_ARRAYTYPE_P(class_count_array); }
/* * The step function for the aggregation of splitting criteria values. It accumulates * all the information for scv calculation and stores to a fourteen element array. * * Parameters: * scv_state_array The array used to accumulate all the information for the * calculation of splitting criteria values. Please refer to * the definition of SCV_STATE_ARRAY_INDEX. * split_criterion 1- infogain; 2- gainratio; 3- gini. * feature_val The feature value of current record under processing. * class The class of current record under processing. * is_cont_feature True- The feature is continuous. False- The feature is * discrete. * less Count of elements less than or equal to feature_val. * great Count of elements greater than feature_val. * true_total_count If there is any missing value, true_total_count is larger than * the total count computed in the aggregation. Thus, we should * multiply a ratio for the computed gain. * Return: * A fourteen element array. Please refer to the definition of * SCV_STATE_ARRAY_INDEX for the detailed information of this * array. */ Datum scv_aggr_sfunc(PG_FUNCTION_ARGS) { ArrayType* scv_state_array = NULL; if (fcinfo->context && IsA(fcinfo->context, AggState)) scv_state_array = PG_GETARG_ARRAYTYPE_P(0); else scv_state_array = PG_GETARG_ARRAYTYPE_P_COPY(0); check_error ( scv_state_array, "invalid aggregation state array" ); int array_dim = ARR_NDIM(scv_state_array); check_error_value ( array_dim == 1, "invalid array dimension: %d. The dimension of scv state array must be equal to 1", array_dim ); int* p_array_dim = ARR_DIMS(scv_state_array); int array_length = ArrayGetNItems(array_dim, p_array_dim); check_error_value ( array_length == SCV_STATE_MAX_CLASS_ELEM_COUNT + 1, "invalid array length: %d", array_length ); float8 *scv_state_data = (float8 *)ARR_DATA_PTR(scv_state_array); check_error ( scv_state_data, "invalid aggregation data array" ); int split_criterion = PG_GETARG_INT32(1); bool is_null_fval = PG_ARGISNULL(2); float8 feature_val = PG_GETARG_FLOAT8(2); float8 class = PG_ARGISNULL(3) ? -1 : PG_GETARG_FLOAT8(3); bool is_cont_feature = PG_ARGISNULL(4) ? false : PG_GETARG_BOOL(4); float8 less = PG_ARGISNULL(5) ? 0 : PG_GETARG_FLOAT8(5); float8 great = PG_ARGISNULL(6) ? 0 : PG_GETARG_FLOAT8(6); float8 true_total_count = PG_ARGISNULL(7) ? 0 : PG_GETARG_FLOAT8(7); check_error_value ( (SC_INFOGAIN == split_criterion || SC_GAINRATIO == split_criterion || SC_GINI == split_criterion), "invalid split criterion: %d. It must be 1(infogain), 2(gainratio) or 3(gini)", split_criterion ); /* * If the count for total element is still zero * it is the first time that step function is * invoked. In that case, we should initialize * several elements. */ if (is_float_zero(scv_state_data[SCV_STATE_TOTAL_ELEM_COUNT])) { scv_state_data[SCV_STATE_SPLIT_CRIT] = split_criterion; if (SC_GINI == split_criterion) { scv_state_data[SCV_STATE_INIT_SCV] = 1; } else { scv_state_data[SCV_STATE_INIT_SCV] = 0; } scv_state_data[SCV_STATE_IS_CONT] = is_cont_feature ? 1 : 0; scv_state_data[SCV_STATE_TRUE_TOTAL_COUNT] = true_total_count; dtelog(NOTICE,"true_total_count:%lf",true_total_count); } float8 temp_float = 0; if( is_null_fval ) { dtelog(NOTICE,"is_null_fval:%d",is_null_fval); if( !is_cont_feature ) { if( class <0 ) { scv_state_data[SCV_STATE_TOTAL_ELEM_COUNT] = less; dtelog(NOTICE,"SCV_STATE_TOTAL_ELEM_COUNT:%lf",less); } else { if (scv_state_data[SCV_STATE_MAX_CLASS_ELEM_COUNT] < less) { scv_state_data[SCV_STATE_MAX_CLASS_ELEM_COUNT] = less; scv_state_data[SCV_STATE_MAX_CLASS_ID] = class; } accumulate_pre_split_scv( scv_state_data, less, scv_state_data[SCV_STATE_TOTAL_ELEM_COUNT], split_criterion); } }
/* ** The GiST Consistent method for _intments ** Should return false if for all data items x below entry, ** the predicate x op query == FALSE, where op is the oper ** corresponding to strategy in the pg_amop table. */ Datum g_int_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); ArrayType *query = PG_GETARG_ARRAYTYPE_P_COPY(1); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); /* Oid subtype = PG_GETARG_OID(3); */ bool *recheck = (bool *) PG_GETARG_POINTER(4); bool retval; /* this is exact except for RTSameStrategyNumber */ *recheck = (strategy == RTSameStrategyNumber); if (strategy == BooleanSearchStrategy) { retval = execconsistent((QUERYTYPE *) query, (ArrayType *) DatumGetPointer(entry->key), GIST_LEAF(entry)); pfree(query); PG_RETURN_BOOL(retval); } /* sort query for fast search, key is already sorted */ CHECKARRVALID(query); PREPAREARR(query); switch (strategy) { case RTOverlapStrategyNumber: retval = inner_int_overlap((ArrayType *) DatumGetPointer(entry->key), query); break; case RTSameStrategyNumber: if (GIST_LEAF(entry)) DirectFunctionCall3(g_int_same, entry->key, PointerGetDatum(query), PointerGetDatum(&retval)); else retval = inner_int_contains((ArrayType *) DatumGetPointer(entry->key), query); break; case RTContainsStrategyNumber: case RTOldContainsStrategyNumber: retval = inner_int_contains((ArrayType *) DatumGetPointer(entry->key), query); break; case RTContainedByStrategyNumber: case RTOldContainedByStrategyNumber: if (GIST_LEAF(entry)) retval = inner_int_contains(query, (ArrayType *) DatumGetPointer(entry->key)); else retval = inner_int_overlap((ArrayType *) DatumGetPointer(entry->key), query); break; default: retval = FALSE; } pfree(query); PG_RETURN_BOOL(retval); }
Datum internal_kmeans_agg_centroid_trans(PG_FUNCTION_ARGS) { ArrayType *array = NULL; ArrayType *cent_array = NULL; int32 dimension; int32 num_of_centroids; int32 centroid_index; bool rebuild_array = false; int32 expected_array_len; float8 *c_array = NULL; cent_array = PG_GETARG_ARRAYTYPE_P(verify_arg_nonnull(fcinfo, 1)); int array_dim = ARR_NDIM(cent_array); int *p_array_dim = ARR_DIMS(cent_array); int array_length = ArrayGetNItems(array_dim, p_array_dim); float8* c_cent_array = (float8 *)ARR_DATA_PTR(cent_array); dimension = PG_GETARG_INT32(verify_arg_nonnull(fcinfo, 2)); num_of_centroids = PG_GETARG_INT32(verify_arg_nonnull(fcinfo, 3)); centroid_index = PG_GETARG_INT32(verify_arg_nonnull(fcinfo, 4)); expected_array_len = num_of_centroids*dimension; if (dimension < 1) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("function \"%s\", Invalid dimension:%d", format_procedure(fcinfo->flinfo->fn_oid), dimension))); } if (array_length != dimension) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("function \"%s\", Inconsistent Dimension. " "Expected:%d, Actual:%d", format_procedure(fcinfo->flinfo->fn_oid), dimension, array_length))); } if (num_of_centroids < 1) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("function \"%s\", Invalid num_of_centroids:%d", format_procedure(fcinfo->flinfo->fn_oid), num_of_centroids))); } if (centroid_index < 1 || centroid_index>num_of_centroids) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("function \"%s\", Invalid centroid_index:%d", format_procedure(fcinfo->flinfo->fn_oid), centroid_index))); } if (PG_ARGISNULL(0)) { c_array = palloc0(expected_array_len*sizeof(float8)); rebuild_array = true; } else { if (fcinfo->context && IsA(fcinfo->context, AggState)) array = PG_GETARG_ARRAYTYPE_P(0); else array = PG_GETARG_ARRAYTYPE_P_COPY(0); array_dim = ARR_NDIM(array); p_array_dim = ARR_DIMS(array); array_length = ArrayGetNItems(array_dim, p_array_dim); if (array_length != expected_array_len) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("function \"%s\", Invalid array length. " "Expected: %d, Actual:%d", format_procedure(fcinfo->flinfo->fn_oid), expected_array_len, array_length))); } c_array = (float8 *)ARR_DATA_PTR(array); } float8 * data_ptr = c_array+(centroid_index-1)*dimension; for(int index=0; index<dimension; index++) { data_ptr[index] = c_cent_array[index]; } if (rebuild_array) { /* construct a new array to keep the aggr states. */ array = construct_array( (Datum *)c_array, expected_array_len, FLOAT8OID, sizeof(float8), true, 'd' ); } PG_RETURN_ARRAYTYPE_P(array); }
Datum tsa_rewrite_accum(PG_FUNCTION_ARGS) { TSQuery acc; ArrayType *qa; TSQuery q; QTNode *qex = NULL, *subs = NULL, *acctree = NULL; bool isfind = false; Datum *elemsp; int nelemsp; MemoryContext aggcontext; MemoryContext oldcontext; aggcontext = ((AggState *) fcinfo->context)->aggcontext; if (PG_ARGISNULL(0) || PG_GETARG_POINTER(0) == NULL) { acc = (TSQuery) MemoryContextAlloc(aggcontext, HDRSIZETQ); SET_VARSIZE(acc, HDRSIZETQ); acc->size = 0; } else acc = PG_GETARG_TSQUERY(0); if (PG_ARGISNULL(1) || PG_GETARG_POINTER(1) == NULL) PG_RETURN_TSQUERY(acc); else qa = PG_GETARG_ARRAYTYPE_P_COPY(1); if (ARR_NDIM(qa) != 1) elog(ERROR, "array must be one-dimensional, not %d dimensions", ARR_NDIM(qa)); if (ArrayGetNItems(ARR_NDIM(qa), ARR_DIMS(qa)) != 3) elog(ERROR, "array must have three elements"); if (ARR_ELEMTYPE(qa) != TSQUERYOID) elog(ERROR, "array must contain tsquery elements"); deconstruct_array(qa, TSQUERYOID, -1, false, 'i', &elemsp, NULL, &nelemsp); q = DatumGetTSQuery(elemsp[0]); if (q->size == 0) { pfree(elemsp); PG_RETURN_POINTER(acc); } if (!acc->size) { if (VARSIZE(acc) > HDRSIZETQ) { pfree(elemsp); PG_RETURN_POINTER(acc); } else acctree = QT2QTN(GETQUERY(q), GETOPERAND(q)); } else acctree = QT2QTN(GETQUERY(acc), GETOPERAND(acc)); QTNTernary(acctree); QTNSort(acctree); q = DatumGetTSQuery(elemsp[1]); if (q->size == 0) { pfree(elemsp); PG_RETURN_POINTER(acc); } qex = QT2QTN(GETQUERY(q), GETOPERAND(q)); QTNTernary(qex); QTNSort(qex); q = DatumGetTSQuery(elemsp[2]); if (q->size) subs = QT2QTN(GETQUERY(q), GETOPERAND(q)); acctree = findsubquery(acctree, qex, subs, &isfind); if (isfind || !acc->size) { /* pfree( acc ); do not pfree(p), because nodeAgg.c will */ if (acctree) { QTNBinary(acctree); oldcontext = MemoryContextSwitchTo(aggcontext); acc = QTN2QT(acctree); MemoryContextSwitchTo(oldcontext); } else { acc = (TSQuery) MemoryContextAlloc(aggcontext, HDRSIZETQ); SET_VARSIZE(acc, HDRSIZETQ); acc->size = 0; } } pfree(elemsp); QTNFree(qex); QTNFree(subs); QTNFree(acctree); PG_RETURN_TSQUERY(acc); }
/* * The pre-function for REP. It takes two class count arrays * produced by the sfunc and combine them together. * * Parameters: * 1 arg: The array returned by sfun1 * 2 arg: The array returned by sfun2 * Return: * The array with the combined information */ Datum rep_aggr_class_count_prefunc(PG_FUNCTION_ARGS) { ArrayType *class_count_array = NULL; int array_dim = 0; int *p_array_dim = NULL; int array_length = 0; int64 *class_count_data = NULL; ArrayType *class_count_array2 = NULL; int array_dim2 = 0; int *p_array_dim2 = NULL; int array_length2 = 0; int64 *class_count_data2 = NULL; if (PG_ARGISNULL(0) && PG_ARGISNULL(1)) PG_RETURN_NULL(); else if (PG_ARGISNULL(1) || PG_ARGISNULL(0)) { /* If one of the two array is null, just return the non-null array directly */ PG_RETURN_ARRAYTYPE_P(PG_ARGISNULL(1) ? PG_GETARG_ARRAYTYPE_P(0) : PG_GETARG_ARRAYTYPE_P(1)); } else { /* * If both arrays are not null, we will merge them together. */ if (fcinfo->context && IsA(fcinfo->context, AggState)) class_count_array = PG_GETARG_ARRAYTYPE_P(0); else class_count_array = PG_GETARG_ARRAYTYPE_P_COPY(0); check_error ( class_count_array, "invalid aggregation state array" ); array_dim = ARR_NDIM(class_count_array); check_error_value ( array_dim == 1, "invalid array dimension: %d. The dimension of class count array must be equal to 1", array_dim ); p_array_dim = ARR_DIMS(class_count_array); array_length = ArrayGetNItems(array_dim,p_array_dim); class_count_data = (int64 *)ARR_DATA_PTR(class_count_array); class_count_array2 = PG_GETARG_ARRAYTYPE_P(1); array_dim2 = ARR_NDIM(class_count_array2); check_error_value ( array_dim2 == 1, "invalid array dimension: %d. The dimension of class count array must be equal to 1", array_dim2 ); p_array_dim2 = ARR_DIMS(class_count_array2); array_length2 = ArrayGetNItems(array_dim2,p_array_dim2); class_count_data2 = (int64 *)ARR_DATA_PTR(class_count_array2); check_error ( array_length == array_length2, "the size of the two array must be the same in prefunction" ); for (int index = 0; index < array_length; index++) class_count_data[index] += class_count_data2[index]; PG_RETURN_ARRAYTYPE_P(class_count_array); } }