/*----------------------------------------------------------------------------- * array_prepend : * push an element onto the front of a one-dimensional array *---------------------------------------------------------------------------- */ Datum array_prepend(PG_FUNCTION_ARGS) { ArrayType *v; Datum newelem; bool isNull; ArrayType *result; int *lb; int indx; ArrayMetaState *my_extra; isNull = PG_ARGISNULL(0); if (isNull) newelem = (Datum) 0; else newelem = PG_GETARG_DATUM(0); v = fetch_array_arg_replace_nulls(fcinfo, 1); if (ARR_NDIM(v) == 1) { /* prepend newelem */ lb = ARR_LBOUND(v); indx = lb[0] - 1; /* overflow? */ if (indx > lb[0]) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); } else if (ARR_NDIM(v) == 0) indx = 1; else ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("argument must be empty or one-dimensional array"))); /* Perform element insertion */ my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; result = array_set(v, 1, &indx, newelem, isNull, -1, my_extra->typlen, my_extra->typbyval, my_extra->typalign); /* Readjust result's LB to match the input's, as expected for prepend */ if (ARR_NDIM(v) == 1) ARR_LBOUND(result)[0] = ARR_LBOUND(v)[0]; PG_RETURN_ARRAYTYPE_P(result); }
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); } } }
static PyObj array_get_lowerbounds(PyObj self, void *closure) { ArrayType *at; PyObj rob; int i, ndim, *lbs; at = DatumGetArrayTypeP(PyPgObject_GetDatum(self)); ndim = ARR_NDIM(at); lbs = ARR_LBOUND(at); rob = PyTuple_New(ndim); for (i = 0; i < ndim; ++i) { PyObj ob; ob = PyLong_FromLong(lbs[i]); if (ob == NULL) { Py_DECREF(rob); return(NULL); } PyTuple_SET_ITEM(rob, i, ob); } return(rob); }
/* 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; }
static int intArrayIdx(ArrayType * array, int const * coord, bool noerror) { int * lbs; int * dims; int i, res; lbs = ARR_LBOUND(array); dims = ARR_DIMS(array); res = 0; for (i = 0; i < array->ndim; i++) { int c = coord[i] - lbs[i]; if (c < 0 || c >= dims[i]) { if (noerror) return -1; else elog(ERROR, "array out of bounds"); } res = res * dims[i] + c; } return res; }
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; }
static ArrayType * intArrayInit(int ndims, int const * dims, int const * lbs) { ArrayType * res; int size; int nbytes; if (ndims < 0) /* we do allow zero-dimension arrays */ ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid number of dimensions: %d", ndims))); if (ndims > MAXDIM) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)", ndims, MAXDIM))); /* fast track for empty array */ if (ndims == 0) return construct_empty_array(INT4OID); size = ArrayGetNItems(ndims, dims); nbytes = ARR_OVERHEAD_NONULLS(ndims); nbytes += size * 4; res = palloc0(nbytes); SET_VARSIZE(res, nbytes); res->ndim = ndims; res->elemtype = INT4OID; res->dataoffset = 0; memcpy(ARR_DIMS(res), dims, ndims * sizeof(int)); memcpy(ARR_LBOUND(res), lbs, ndims * sizeof(int)); return res; }
Datum hstore_slice_to_array(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); HEntry *entries = ARRPTR(hs); char *ptr = STRPTR(hs); ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(1); ArrayType *aout; Datum *key_datums; bool *key_nulls; Datum *out_datums; bool *out_nulls; int key_count; int i; deconstruct_array(key_array, TEXTOID, -1, false, 'i', &key_datums, &key_nulls, &key_count); if (key_count == 0) { aout = construct_empty_array(TEXTOID); PG_RETURN_POINTER(aout); } out_datums = palloc(sizeof(Datum) * key_count); out_nulls = palloc(sizeof(bool) * key_count); for (i = 0; i < key_count; ++i) { text *key = (text *) DatumGetPointer(key_datums[i]); int idx; if (key_nulls[i]) idx = -1; else idx = hstoreFindKey(hs, NULL, VARDATA(key), VARSIZE(key) - VARHDRSZ); if (idx < 0 || HS_VALISNULL(entries, idx)) { out_nulls[i] = true; out_datums[i] = (Datum) 0; } else { out_datums[i] = PointerGetDatum( cstring_to_text_with_len(HS_VAL(entries, ptr, idx), HS_VALLEN(entries, idx))); out_nulls[i] = false; } } aout = construct_md_array(out_datums, out_nulls, ARR_NDIM(key_array), ARR_DIMS(key_array), ARR_LBOUND(key_array), TEXTOID, -1, false, 'i'); PG_RETURN_POINTER(aout); }
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); }
inline AbstractionLayer::MutableArrayHandle<T> AbstractionLayer::Allocator::allocateArray(size_t inNumElements) const { /* * Check that the size will not exceed addressable memory. Therefore, the * following precondition has to hold: * ((std::numeric_limits<size_t>::max() - ARR_OVERHEAD_NONULLS(1)) / * inElementSize >= inNumElements) */ if ((std::numeric_limits<size_t>::max() - ARR_OVERHEAD_NONULLS(1)) / sizeof(T) < inNumElements) throw std::bad_alloc(); size_t size = sizeof(T) * inNumElements + ARR_OVERHEAD_NONULLS(1); ArrayType *array; // Note: Except for the allocate call, the following statements do not call // into the PostgreSQL backend. We are only using macros here. // PostgreSQL requires that all memory is overwritten with zeros. So // we ingore ZM here array = static_cast<ArrayType*>(allocate<MC, dbal::DoZero, F>(size)); SET_VARSIZE(array, size); array->ndim = 1; array->dataoffset = 0; array->elemtype = TypeTraits<T>::oid; ARR_DIMS(array)[0] = inNumElements; ARR_LBOUND(array)[0] = 1; return MutableArrayHandle<T>(array); }
Datum alpine_miner_lr_ca_derivative(PG_FUNCTION_ARGS) { ArrayType *beta_arg, *columns_arg, *result; float8 *beta_data, *columns_data, *result_data; int beta_count, columns_count, result_count; bool add_intercept_arg; double weight_arg; int y_arg; int size; double gx = 0.0; double pi = 0.0; if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3) || PG_ARGISNULL(4) || PG_ARGISNULL(5)){ PG_RETURN_NULL(); } result = PG_GETARG_ARRAYTYPE_P(0); beta_arg = PG_GETARG_ARRAYTYPE_P(1); columns_arg = PG_GETARG_ARRAYTYPE_P(2); add_intercept_arg = PG_GETARG_BOOL(3); weight_arg = PG_GETARG_FLOAT8(4); y_arg = PG_GETARG_INT32(5); result_data = (float8*) ARR_DATA_PTR(result); beta_data = (float8*) ARR_DATA_PTR(beta_arg); columns_data = (float8*) ARR_DATA_PTR(columns_arg); result_count = ARR_DIMS(result)[0]; beta_count = ARR_DIMS(beta_arg)[0]; columns_count = ARR_DIMS(columns_arg)[0]; // float8 * column_array_data = (float8*) ARR_DATA_PTR(column_array); if (result_count == 1){ result_count = beta_count; size = result_count * sizeof(float8) + ARR_OVERHEAD_NONULLS(1); result = (ArrayType *) palloc(size); SET_VARSIZE(result, size); result->ndim = 1; result->dataoffset = 0; result->elemtype = FLOAT8OID; ARR_DIMS(result)[0] = result_count; ARR_LBOUND(result)[0] = 1; result_data = (float8*) ARR_DATA_PTR(result); memset(result_data, 0, result_count * sizeof(float8)); } pi = alpine_miner_compute_pi(beta_data, beta_count, columns_data, columns_count, add_intercept_arg); alpine_miner_compute_derivative(columns_count,columns_data, result_data ,weight_arg, y_arg, add_intercept_arg, pi); PG_RETURN_ARRAYTYPE_P(result); }
Datum alpine_miner_covar_sam_accum(PG_FUNCTION_ARGS) { ArrayType *state; float8 * state_array_data; ArrayType * column_array; int column_size; float8 * column_array_data; int i; int k ; int j; if (PG_ARGISNULL(0)){ PG_RETURN_NULL(); } state = PG_GETARG_ARRAYTYPE_P(0); state_array_data = (float8*) ARR_DATA_PTR(state); column_array = PG_GETARG_ARRAYTYPE_P(1); column_size = ARR_DIMS(column_array)[0]; column_array_data = (float8*) ARR_DATA_PTR(column_array); if (ARR_DIMS(state)[0] == 1){ int result_size = column_size * ( column_size + 1)/2 + column_size+2; int size = result_size * sizeof(float8) + ARR_OVERHEAD_NONULLS(1); state = (ArrayType *) palloc(size); SET_VARSIZE(state, size); state->ndim = 1; state->dataoffset = 0; state->elemtype = FLOAT8OID; ARR_DIMS(state)[0] = result_size; ARR_LBOUND(state)[0] = 1; state_array_data = (float8*) ARR_DATA_PTR(state); memset(state_array_data, 0, result_size * sizeof(float8)); } k = 0; for ( i = 0; i < column_size; i++){ for(j = i; j < column_size; j++){ state_array_data[k] += column_array_data[i] * column_array_data[j]; k++; } } for( i = 0; i < column_size; i++){ state_array_data[k + i] += column_array_data[i]; } state_array_data[k+i]++; state_array_data[k+i+1]=column_size; PG_RETURN_ARRAYTYPE_P(state); }
/*----------------------------------------------------------------------------- * array_append : * push an element onto the end of a one-dimensional array *---------------------------------------------------------------------------- */ Datum array_append(PG_FUNCTION_ARGS) { ArrayType *v; Datum newelem; bool isNull; ArrayType *result; int *dimv, *lb; int indx; ArrayMetaState *my_extra; v = fetch_array_arg_replace_nulls(fcinfo, 0); isNull = PG_ARGISNULL(1); if (isNull) newelem = (Datum) 0; else newelem = PG_GETARG_DATUM(1); if (ARR_NDIM(v) == 1) { /* append newelem */ int ub; lb = ARR_LBOUND(v); dimv = ARR_DIMS(v); ub = dimv[0] + lb[0] - 1; indx = ub + 1; /* overflow? */ if (indx < ub) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); } else if (ARR_NDIM(v) == 0) indx = 1; else ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("argument must be empty or one-dimensional array"))); /* Perform element insertion */ my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; result = array_set(v, 1, &indx, newelem, isNull, -1, my_extra->typlen, my_extra->typbyval, my_extra->typalign); PG_RETURN_ARRAYTYPE_P(result); }
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); }
Datum alpine_miner_covar_sam_final(PG_FUNCTION_ARGS){ ArrayType *state ; ArrayType *result; float8 * resultData; float8 * state_array_data; int total_length; int column_size; float8 row_size; int result_size; int size; int k=0; int i,j; int sam_row_size; if (PG_ARGISNULL(0)) PG_RETURN_NULL(); state = PG_GETARG_ARRAYTYPE_P(0); state_array_data = (float8*) ARR_DATA_PTR(state); total_length=ARR_DIMS(state)[0]; column_size=state_array_data[total_length-1]; row_size=state_array_data[total_length-2]; result_size=column_size*(column_size+1)/2; size = result_size * sizeof(float8) + ARR_OVERHEAD_NONULLS(1); result = (ArrayType *) palloc(size); SET_VARSIZE(result, size); result->ndim = 1; result->dataoffset = 0; result->elemtype = FLOAT8OID; ARR_DIMS(result)[0] = result_size; ARR_LBOUND(result)[0] = 1; resultData = (float8*) ARR_DATA_PTR(result); memset(resultData, 0, result_size * sizeof(float8)); sam_row_size=row_size-1; if(sam_row_size<=0) sam_row_size=1; k=0; for ( i = 0; i < column_size; i++){ for( j = i; j < column_size; j++){ resultData[k] =state_array_data[k]/sam_row_size- state_array_data[result_size+i] * state_array_data[result_size+j]/row_size/sam_row_size; k++; } } PG_RETURN_ARRAYTYPE_P(result); }
/*------------------------------------------------------------------------ * _ReadChunkArray1El -- * returns one element of the chunked array as specified by the index "st" * the chunked file descriptor is "fp" *------------------------------------------------------------------------- */ struct varlena * _ReadChunkArray1El(int st[], int bsize, int fp, ArrayType *array, bool *isNull) { int i, j, n, temp, srcOff; int chunk_st[MAXDIM]; int *C, csize, *dim, *lb; int PCHUNK[MAXDIM], PC[MAXDIM]; CHUNK_INFO *A = (CHUNK_INFO *) ARR_DATA_PTR(array); n = ARR_NDIM(array); lb = ARR_LBOUND(array); C = A->C; dim = ARR_DIMS(array); csize = C[n-1]; PC[n-1] = 1; temp = dim[n - 1]/C[n-1]; for (i = n-2; i >= 0; i--){ PC[i] = PC[i+1] * temp; temp = dim[i] / C[i]; csize *= C[i]; } for (i = 0; i < n; st[i] -= lb[i], i++); mda_get_prod(n, C, PCHUNK); array2chunk_coord(n, C, st, chunk_st); for (i = j = 0; i < n; i++) j+= chunk_st[i]*PC[i]; srcOff = j * csize; for(i = 0; i < n; i++) srcOff += (st[i]-chunk_st[i]*C[i])*PCHUNK[i]; srcOff *= bsize; if (lo_lseek(fp, srcOff, SEEK_SET) < 0) RETURN_NULL; #ifdef LOARRAY return (struct varlena *) LOread(fp, bsize); #endif return (struct varlena *) 0; }
Datum alpine_plda_count_accum(PG_FUNCTION_ARGS) { ArrayType *state; int32 * state_array_data; ArrayType * column_array; ArrayType * assign_array; int32 column_size,assign_size,topicnumber,wordnumber; int32 result_size; int32 size; int32 * column_array_data; int32 * assign_array_data; int32 k; if (PG_ARGISNULL(0)){ PG_RETURN_NULL(); } state = PG_GETARG_ARRAYTYPE_P(0); state_array_data = (int32*) ARR_DATA_PTR(state); column_array = PG_GETARG_ARRAYTYPE_P(1); column_size = ARR_DIMS(column_array)[0]; column_array_data = (int32*) ARR_DATA_PTR(column_array); assign_array=PG_GETARG_ARRAYTYPE_P(2); assign_size = ARR_DIMS(assign_array)[0]; assign_array_data = (int32*) ARR_DATA_PTR(assign_array); topicnumber=PG_GETARG_INT32(3); wordnumber =PG_GETARG_INT32(4); if (ARR_DIMS(state)[0] == 1){ result_size = topicnumber*wordnumber; size = result_size * sizeof(int32) + ARR_OVERHEAD_NONULLS(1); state = (ArrayType *) palloc(size); SET_VARSIZE(state, size); state->ndim = 1; state->dataoffset = 0; state->elemtype = INT4OID; ARR_DIMS(state)[0] = result_size; ARR_LBOUND(state)[0] = 1; state_array_data = (int32*) ARR_DATA_PTR(state); memset(state_array_data, 0, result_size * sizeof(int32)); } for ( k = 0; k < column_size; k++){ state_array_data[topicnumber*(column_array_data[k]-1)+assign_array_data[k]-1]=state_array_data[topicnumber*(column_array_data[k]-1)+assign_array_data[k]-1]+1; } PG_RETURN_ARRAYTYPE_P(state); }
/* * flatten_into method for expanded arrays */ static void EA_flatten_into(ExpandedObjectHeader *eohptr, void *result, Size allocated_size) { ExpandedArrayHeader *eah = (ExpandedArrayHeader *) eohptr; ArrayType *aresult = (ArrayType *) result; int nelems; int ndims; int32 dataoffset; Assert(eah->ea_magic == EA_MAGIC); /* Easy if we have a valid flattened value */ if (eah->fvalue) { Assert(allocated_size == ARR_SIZE(eah->fvalue)); memcpy(result, eah->fvalue, allocated_size); return; } /* Else allocation should match previous get_flat_size result */ Assert(allocated_size == eah->flat_size); /* Fill result array from dvalues/dnulls */ nelems = eah->nelems; ndims = eah->ndims; if (eah->dnulls) dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nelems); else dataoffset = 0; /* marker for no null bitmap */ /* We must ensure that any pad space is zero-filled */ memset(aresult, 0, allocated_size); SET_VARSIZE(aresult, allocated_size); aresult->ndim = ndims; aresult->dataoffset = dataoffset; aresult->elemtype = eah->element_type; memcpy(ARR_DIMS(aresult), eah->dims, ndims * sizeof(int)); memcpy(ARR_LBOUND(aresult), eah->lbound, ndims * sizeof(int)); CopyArrayEls(aresult, eah->dvalues, eah->dnulls, nelems, eah->typlen, eah->typbyval, eah->typalign, false); }
/* * Extract len and pointer to buffer from an int16[] (vector) Datum * representing a PostgreSQL INT2OID type. */ static void extract_INT2OID_array(Datum array_datum, int *lenp, int16 **vecp) { ArrayType *array_type; Assert(lenp != NULL); Assert(vecp != NULL); array_type = DatumGetArrayTypeP(array_datum); Assert(ARR_NDIM(array_type) == 1); Assert(ARR_ELEMTYPE(array_type) == INT2OID); Assert(ARR_LBOUND(array_type)[0] == 1); *lenp = ARR_DIMS(array_type)[0]; *vecp = (int16 *) ARR_DATA_PTR(array_type); return; }
static PyObject * PLyList_FromArray(PLyDatumToOb *arg, Datum d) { ArrayType *array = DatumGetArrayTypeP(d); PLyDatumToOb *elm = arg->elm; PyObject *list; int length; int lbound; int i; if (ARR_NDIM(array) == 0) return PyList_New(0); if (ARR_NDIM(array) != 1) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot convert multidimensional array to Python list"), errdetail("PL/Python only supports one-dimensional arrays."))); length = ARR_DIMS(array)[0]; lbound = ARR_LBOUND(array)[0]; list = PyList_New(length); if (list == NULL) PLy_elog(ERROR, "could not create new Python list"); for (i = 0; i < length; i++) { Datum elem; bool isnull; int offset; offset = lbound + i; elem = array_ref(array, 1, &offset, arg->typlen, elm->typlen, elm->typbyval, elm->typalign, &isnull); if (isnull) { Py_INCREF(Py_None); PyList_SET_ITEM(list, i, Py_None); } else PyList_SET_ITEM(list, i, elm->func(elm, elem)); } return list; }
/* Create a new int array with room for "num" elements */ ArrayType * new_intArrayType(int num) { ArrayType *r; int nbytes = ARR_OVERHEAD_NONULLS(1) + sizeof(int) * num; r = (ArrayType *) palloc0(nbytes); SET_VARSIZE(r, nbytes); ARR_NDIM(r) = 1; r->dataoffset = 0; /* marker for no null bitmap */ ARR_ELEMTYPE(r) = INT4OID; ARR_DIMS(r)[0] = num; ARR_LBOUND(r)[0] = 1; return r; }
/* * int2vectorrecv - converts external binary format to int2_vector_s */ datum_t int2vectorrecv(PG_FUNC_ARGS) { struct string* buf = (struct string*) ARG_POINTER(0); struct fc_info locfcinfo; int2_vector_s *result; /* * Normally one would call array_recv() using DIRECT_FC3, but * that does not work since array_recv wants to cache some data using * fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo * parameter. */ INIT_FC_INFO(locfcinfo, fcinfo->flinfo, 3, INVALID_OID, NULL, NULL); locfcinfo.arg[0] = PTR_TO_D(buf); locfcinfo.arg[1] = OID_TO_D(INT2OID); locfcinfo.arg[2] = INT32_TO_D(-1); locfcinfo.argnull[0] = false; locfcinfo.argnull[1] = false; locfcinfo.argnull[2] = false; result = (int2_vector_s *) D_TO_PTR(array_recv(&locfcinfo)); ASSERT(!locfcinfo.isnull); /* sanity checks: int2_vector_s must be 1-D, 0-based, no nulls */ if (ARR_NDIM(result) != 1 || ARR_HASNULL(result) || ARR_ELEMTYPE(result) != INT2OID || ARR_LBOUND(result)[0] != 0) { ereport(ERROR, ( errcode(E_INVALID_BINARY_REPRESENTATION), errmsg("invalid int2_vector_s data"))); } /* check length for consistency with int2vectorin() */ if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS) { ereport(ERROR, ( errcode(E_INVALID_PARAMETER_VALUE), errmsg("oidvector has too many elements"))); } RET_POINTER(result); }
/* * int2vectorrecv - converts external binary format to int2vector */ Datum int2vectorrecv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); FunctionCallInfoData locfcinfo; int2vector *result; /* * Normally one would call array_recv() using DirectFunctionCall3, but * that does not work since array_recv wants to cache some data using * fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo * parameter. */ InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3, InvalidOid, NULL, NULL); locfcinfo.arg[0] = PointerGetDatum(buf); locfcinfo.arg[1] = ObjectIdGetDatum(INT2OID); locfcinfo.arg[2] = Int32GetDatum(-1); locfcinfo.argnull[0] = false; locfcinfo.argnull[1] = false; locfcinfo.argnull[2] = false; result = (int2vector *) DatumGetPointer(array_recv(&locfcinfo)); Assert(!locfcinfo.isnull); /* sanity checks: int2vector must be 1-D, 0-based, no nulls */ if (ARR_NDIM(result) != 1 || ARR_HASNULL(result) || ARR_ELEMTYPE(result) != INT2OID || ARR_LBOUND(result)[0] != 0) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid int2vector data"))); /* check length for consistency with int2vectorin() */ if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("oidvector has too many elements"))); PG_RETURN_POINTER(result); }
Datum domainname_parts(PG_FUNCTION_ARGS) { text *in = PG_GETARG_TEXT_P(0); const char *s = VARDATA(in); const char *b = s, *p = s, *e = s + VARSIZE_ANY_EXHDR(in); int nelems = 0; int nbytes = ARR_OVERHEAD_NONULLS(1); ArrayType *r; char *o; while (p < e) { b = p; STRSEARCH(p, e-p, *p == '.'); nelems ++; nbytes += VARHDRSZ + (p-b); nbytes = INTALIGN(nbytes); p ++; } r = (ArrayType *)palloc(nbytes); SET_VARSIZE(r, nbytes); r->ndim = 1; r->dataoffset = 0; r->elemtype = TEXTOID; *ARR_DIMS(r) = nelems; *ARR_LBOUND(r) = 1; p = s; o = ARR_DATA_PTR(r); while (p < e) { b = p; STRSEARCH(p, e-p, *p == '.'); SET_VARSIZE(o, VARHDRSZ+(p-b)); o = VARDATA(o); memcpy(o, b, p-b); o += INTALIGN(p-b); p ++; } PG_FREE_IF_COPY(in, 0); PG_RETURN_ARRAYTYPE_P(r); }
inline MutableArrayHandle<T> Allocator::internalAllocateArray( const std::array<std::size_t, Dimensions>& inNumElements) const { std::size_t numElements = Dimensions ? 1 : 0; for (std::size_t i = 0; i < Dimensions; ++i) numElements *= inNumElements[i]; /* * Check that the size will not exceed addressable memory. Therefore, the * following precondition has to hold: * ((std::numeric_limits<std::size_t>::max() * - ARR_OVERHEAD_NONULLS(Dimensions)) / inElementSize >= numElements) */ if ((std::numeric_limits<std::size_t>::max() - ARR_OVERHEAD_NONULLS(Dimensions)) / sizeof(T) < numElements) throw std::bad_alloc(); std::size_t size = sizeof(T) * numElements + ARR_OVERHEAD_NONULLS(Dimensions); ArrayType *array; // Note: Except for the allocate call, the following statements do not call // into the PostgreSQL backend. We are only using macros here. // PostgreSQL requires that all memory is overwritten with zeros. So // we ingore ZM here array = static_cast<ArrayType*>(allocate<MC, dbal::DoZero, F>(size)); SET_VARSIZE(array, size); array->ndim = Dimensions; array->dataoffset = 0; array->elemtype = TypeTraits<T>::oid; for (std::size_t i = 0; i < Dimensions; ++i) { ARR_DIMS(array)[i] = static_cast<int>(inNumElements[i]); ARR_LBOUND(array)[i] = 1; } return MutableArrayHandle<T>(array); }
Datum internal_kmeans_canopy_transition(PG_FUNCTION_ARGS) { ArrayType *canopies_arr; Datum *canopies; int num_canopies; SvecType *point; PGFunction metric_fn; float8 threshold; MemoryContext mem_context_for_function_calls; canopies_arr = PG_GETARG_ARRAYTYPE_P(verify_arg_nonnull(fcinfo, 0)); get_svec_array_elms(canopies_arr, &canopies, &num_canopies); point = PG_GETARG_SVECTYPE_P(verify_arg_nonnull(fcinfo, 1)); metric_fn = get_metric_fn(PG_GETARG_INT32(verify_arg_nonnull(fcinfo, 2))); threshold = PG_GETARG_FLOAT8(verify_arg_nonnull(fcinfo, 3)); mem_context_for_function_calls = setup_mem_context_for_functional_calls(); for (int i = 0; i < num_canopies; i++) { if (compute_metric(metric_fn, mem_context_for_function_calls, PointerGetDatum(point), canopies[i]) < threshold) PG_RETURN_ARRAYTYPE_P(canopies_arr); } MemoryContextDelete(mem_context_for_function_calls); int idx = (ARR_NDIM(canopies_arr) == 0) ? 1 : ARR_LBOUND(canopies_arr)[0] + ARR_DIMS(canopies_arr)[0]; return PointerGetDatum( array_set( canopies_arr, /* array: the initial array object (mustn't be NULL) */ 1, /* nSubscripts: number of subscripts supplied */ &idx, /* indx[]: the subscript values */ PointerGetDatum(point), /* dataValue: the datum to be inserted at the given position */ false, /* isNull: whether dataValue is NULL */ -1, /* arraytyplen: pg_type.typlen for the array type */ -1, /* elmlen: pg_type.typlen for the array's element type */ false, /* elmbyval: pg_type.typbyval for the array's element type */ 'd') /* elmalign: pg_type.typalign for the array's element type */ ); }
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); }
/*----------------------------------------------------------------------------- * array_push : * push an element onto either end of a one-dimensional array *---------------------------------------------------------------------------- */ Datum array_push(PG_FUNCTION_ARGS) { ArrayType *v; Datum newelem; bool isNull; int *dimv, *lb; ArrayType *result; int indx; Oid element_type; int16 typlen; bool typbyval; char typalign; Oid arg0_typeid = get_fn_expr_argtype(fcinfo->flinfo, 0); Oid arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1); Oid arg0_elemid; Oid arg1_elemid; ArrayMetaState *my_extra; if (arg0_typeid == InvalidOid || arg1_typeid == InvalidOid) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("could not determine input data types"))); arg0_elemid = get_element_type(arg0_typeid); arg1_elemid = get_element_type(arg1_typeid); if (arg0_elemid != InvalidOid) { if (PG_ARGISNULL(0)) v = construct_empty_array(arg0_elemid); else v = PG_GETARG_ARRAYTYPE_P(0); isNull = PG_ARGISNULL(1); if (isNull) newelem = (Datum) 0; else newelem = PG_GETARG_DATUM(1); } else if (arg1_elemid != InvalidOid) { if (PG_ARGISNULL(1)) v = construct_empty_array(arg1_elemid); else v = PG_GETARG_ARRAYTYPE_P(1); isNull = PG_ARGISNULL(0); if (isNull) newelem = (Datum) 0; else newelem = PG_GETARG_DATUM(0); } else { /* Shouldn't get here given proper type checking in parser */ ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("neither input type is an array"))); PG_RETURN_NULL(); /* keep compiler quiet */ } element_type = ARR_ELEMTYPE(v); if (ARR_NDIM(v) == 1) { lb = ARR_LBOUND(v); dimv = ARR_DIMS(v); if (arg0_elemid != InvalidOid) { /* append newelem */ int ub = dimv[0] + lb[0] - 1; indx = ub + 1; /* overflow? */ if (indx < ub) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); } else { /* prepend newelem */ indx = lb[0] - 1; /* overflow? */ if (indx > lb[0]) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); } } else if (ARR_NDIM(v) == 0) indx = 1; else ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("argument must be empty or one-dimensional array"))); /* * We arrange to look up info about element type only once per series of * calls, assuming the element type doesn't change underneath us. */ my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; if (my_extra == NULL) { fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(ArrayMetaState)); my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; my_extra->element_type = ~element_type; } if (my_extra->element_type != element_type) { /* Get info about element type */ get_typlenbyvalalign(element_type, &my_extra->typlen, &my_extra->typbyval, &my_extra->typalign); my_extra->element_type = element_type; } typlen = my_extra->typlen; typbyval = my_extra->typbyval; typalign = my_extra->typalign; result = array_set(v, 1, &indx, newelem, isNull, -1, typlen, typbyval, typalign); /* * Readjust result's LB to match the input's. This does nothing in the * append case, but it's the simplest way to implement the prepend case. */ if (ARR_NDIM(v) == 1) ARR_LBOUND(result)[0] = ARR_LBOUND(v)[0]; PG_RETURN_ARRAYTYPE_P(result); }
/*----------------------------------------------------------------------------- * array_cat : * concatenate two nD arrays to form an nD array, or * push an (n-1)D array onto the end of an nD array *---------------------------------------------------------------------------- */ Datum array_cat(PG_FUNCTION_ARGS) { ArrayType *v1, *v2; ArrayType *result; int *dims, *lbs, ndims, nitems, ndatabytes, nbytes; int *dims1, *lbs1, ndims1, nitems1, ndatabytes1; int *dims2, *lbs2, ndims2, nitems2, ndatabytes2; int i; char *dat1, *dat2; bits8 *bitmap1, *bitmap2; Oid element_type; Oid element_type1; Oid element_type2; int32 dataoffset; /* Concatenating a null array is a no-op, just return the other input */ if (PG_ARGISNULL(0)) { if (PG_ARGISNULL(1)) PG_RETURN_NULL(); result = PG_GETARG_ARRAYTYPE_P(1); PG_RETURN_ARRAYTYPE_P(result); } if (PG_ARGISNULL(1)) { result = PG_GETARG_ARRAYTYPE_P(0); PG_RETURN_ARRAYTYPE_P(result); } v1 = PG_GETARG_ARRAYTYPE_P(0); v2 = PG_GETARG_ARRAYTYPE_P(1); element_type1 = ARR_ELEMTYPE(v1); element_type2 = ARR_ELEMTYPE(v2); /* Check we have matching element types */ if (element_type1 != element_type2) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("cannot concatenate incompatible arrays"), errdetail("Arrays with element types %s and %s are not " "compatible for concatenation.", format_type_be(element_type1), format_type_be(element_type2)))); /* OK, use it */ element_type = element_type1; /*---------- * We must have one of the following combinations of inputs: * 1) one empty array, and one non-empty array * 2) both arrays empty * 3) two arrays with ndims1 == ndims2 * 4) ndims1 == ndims2 - 1 * 5) ndims1 == ndims2 + 1 *---------- */ ndims1 = ARR_NDIM(v1); ndims2 = ARR_NDIM(v2); /* * short circuit - if one input array is empty, and the other is not, we * return the non-empty one as the result * * if both are empty, return the first one */ if (ndims1 == 0 && ndims2 > 0) PG_RETURN_ARRAYTYPE_P(v2); if (ndims2 == 0) PG_RETURN_ARRAYTYPE_P(v1); /* the rest fall under rule 3, 4, or 5 */ if (ndims1 != ndims2 && ndims1 != ndims2 - 1 && ndims1 != ndims2 + 1) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("cannot concatenate incompatible arrays"), errdetail("Arrays of %d and %d dimensions are not " "compatible for concatenation.", ndims1, ndims2))); /* get argument array details */ lbs1 = ARR_LBOUND(v1); lbs2 = ARR_LBOUND(v2); dims1 = ARR_DIMS(v1); dims2 = ARR_DIMS(v2); dat1 = ARR_DATA_PTR(v1); dat2 = ARR_DATA_PTR(v2); bitmap1 = ARR_NULLBITMAP(v1); bitmap2 = ARR_NULLBITMAP(v2); nitems1 = ArrayGetNItems(ndims1, dims1); nitems2 = ArrayGetNItems(ndims2, dims2); ndatabytes1 = ARR_SIZE(v1) - ARR_DATA_OFFSET(v1); ndatabytes2 = ARR_SIZE(v2) - ARR_DATA_OFFSET(v2); if (ndims1 == ndims2) { /* * resulting array is made up of the elements (possibly arrays * themselves) of the input argument arrays */ ndims = ndims1; dims = (int *) palloc(ndims * sizeof(int)); lbs = (int *) palloc(ndims * sizeof(int)); dims[0] = dims1[0] + dims2[0]; lbs[0] = lbs1[0]; for (i = 1; i < ndims; i++) { if (dims1[i] != dims2[i] || lbs1[i] != lbs2[i]) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("cannot concatenate incompatible arrays"), errdetail("Arrays with differing element dimensions are " "not compatible for concatenation."))); dims[i] = dims1[i]; lbs[i] = lbs1[i]; } } else if (ndims1 == ndims2 - 1) { /* * resulting array has the second argument as the outer array, with * the first argument inserted at the front of the outer dimension */ ndims = ndims2; dims = (int *) palloc(ndims * sizeof(int)); lbs = (int *) palloc(ndims * sizeof(int)); memcpy(dims, dims2, ndims * sizeof(int)); memcpy(lbs, lbs2, ndims * sizeof(int)); /* increment number of elements in outer array */ dims[0] += 1; /* make sure the added element matches our existing elements */ for (i = 0; i < ndims1; i++) { if (dims1[i] != dims[i + 1] || lbs1[i] != lbs[i + 1]) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("cannot concatenate incompatible arrays"), errdetail("Arrays with differing dimensions are not " "compatible for concatenation."))); } } else { /* * (ndims1 == ndims2 + 1) * * resulting array has the first argument as the outer array, with the * second argument appended to the end of the outer dimension */ ndims = ndims1; dims = (int *) palloc(ndims * sizeof(int)); lbs = (int *) palloc(ndims * sizeof(int)); memcpy(dims, dims1, ndims * sizeof(int)); memcpy(lbs, lbs1, ndims * sizeof(int)); /* increment number of elements in outer array */ dims[0] += 1; /* make sure the added element matches our existing elements */ for (i = 0; i < ndims2; i++) { if (dims2[i] != dims[i + 1] || lbs2[i] != lbs[i + 1]) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("cannot concatenate incompatible arrays"), errdetail("Arrays with differing dimensions are not " "compatible for concatenation."))); } } /* Do this mainly for overflow checking */ nitems = ArrayGetNItems(ndims, dims); /* build the result array */ ndatabytes = ndatabytes1 + ndatabytes2; if (ARR_HASNULL(v1) || ARR_HASNULL(v2)) { dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems); nbytes = ndatabytes + dataoffset; } else { dataoffset = 0; /* marker for no null bitmap */ nbytes = ndatabytes + ARR_OVERHEAD_NONULLS(ndims); } result = (ArrayType *) palloc(nbytes); SET_VARSIZE(result, nbytes); result->ndim = ndims; result->dataoffset = dataoffset; result->elemtype = element_type; memcpy(ARR_DIMS(result), dims, ndims * sizeof(int)); memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int)); /* data area is arg1 then arg2 */ memcpy(ARR_DATA_PTR(result), dat1, ndatabytes1); memcpy(ARR_DATA_PTR(result) + ndatabytes1, dat2, ndatabytes2); /* handle the null bitmap if needed */ if (ARR_HASNULL(result)) { array_bitmap_copy(ARR_NULLBITMAP(result), 0, bitmap1, 0, nitems1); array_bitmap_copy(ARR_NULLBITMAP(result), nitems1, bitmap2, 0, nitems2); } PG_RETURN_ARRAYTYPE_P(result); }
Datum hstore_from_arrays(PG_FUNCTION_ARGS) { int4 buflen; HStore *out; Pairs *pairs; Datum *key_datums; bool *key_nulls; int key_count; Datum *value_datums; bool *value_nulls; int value_count; ArrayType *key_array; ArrayType *value_array; int i; if (PG_ARGISNULL(0)) PG_RETURN_NULL(); key_array = PG_GETARG_ARRAYTYPE_P(0); Assert(ARR_ELEMTYPE(key_array) == TEXTOID); /* * must check >1 rather than != 1 because empty arrays have 0 dimensions, * not 1 */ if (ARR_NDIM(key_array) > 1) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("wrong number of array subscripts"))); deconstruct_array(key_array, TEXTOID, -1, false, 'i', &key_datums, &key_nulls, &key_count); /* value_array might be NULL */ if (PG_ARGISNULL(1)) { value_array = NULL; value_count = key_count; value_datums = NULL; value_nulls = NULL; } else { value_array = PG_GETARG_ARRAYTYPE_P(1); Assert(ARR_ELEMTYPE(value_array) == TEXTOID); if (ARR_NDIM(value_array) > 1) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("wrong number of array subscripts"))); if ((ARR_NDIM(key_array) > 0 || ARR_NDIM(value_array) > 0) && (ARR_NDIM(key_array) != ARR_NDIM(value_array) || ARR_DIMS(key_array)[0] != ARR_DIMS(value_array)[0] || ARR_LBOUND(key_array)[0] != ARR_LBOUND(value_array)[0])) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("arrays must have same bounds"))); deconstruct_array(value_array, TEXTOID, -1, false, 'i', &value_datums, &value_nulls, &value_count); Assert(key_count == value_count); } pairs = palloc(key_count * sizeof(Pairs)); for (i = 0; i < key_count; ++i) { if (key_nulls[i]) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("null value not allowed for hstore key"))); if (!value_nulls || value_nulls[i]) { pairs[i].key = VARDATA_ANY(key_datums[i]); pairs[i].val = NULL; pairs[i].keylen = hstoreCheckKeyLen(VARSIZE_ANY_EXHDR(key_datums[i])); pairs[i].vallen = 4; pairs[i].isnull = true; pairs[i].needfree = false; } else { pairs[i].key = VARDATA_ANY(key_datums[i]); pairs[i].val = VARDATA_ANY(value_datums[i]); pairs[i].keylen = hstoreCheckKeyLen(VARSIZE_ANY_EXHDR(key_datums[i])); pairs[i].vallen = hstoreCheckValLen(VARSIZE_ANY_EXHDR(value_datums[i])); pairs[i].isnull = false; pairs[i].needfree = false; } } key_count = hstoreUniquePairs(pairs, key_count, &buflen); out = hstorePairs(pairs, key_count, buflen); PG_RETURN_POINTER(out); }