/* * build_regexp_matches_result - build output array for current match */ static array_s *build_regexp_matches_result(regexp_matches_ctx * matchctx) { datum_t *elems = matchctx->elems; bool *nulls = matchctx->nulls; int dims[1]; int lbs[1]; int loc; int i; /* Extract matching substrings from the original string */ loc = matchctx->next_match * matchctx->npatterns * 2; for (i = 0; i < matchctx->npatterns; i++) { int so = matchctx->match_locs[loc++]; int eo = matchctx->match_locs[loc++]; if (so < 0 || eo < 0) { elems[i] = (datum_t) 0; nulls[i] = true; } else { elems[i] = DIRECT_FC3(text_substr, PTR_TO_D(matchctx->orig_str), INT32_TO_D(so + 1), INT32_TO_D(eo - so)); nulls[i] = false; } } /* And form an array */ dims[0] = matchctx->npatterns; lbs[0] = 1; /* XXX: this hardcodes assumptions about the text type */ return construct_md_array(elems, nulls, 1, dims, lbs, TEXTOID, -1, false, 'i'); }
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); }
/* * 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); }
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); }
/* * build_regexp_matches_result - build output array for current match */ static ArrayType * build_regexp_matches_result(regexp_matches_ctx *matchctx) { char *buf = matchctx->conv_buf; int bufsiz PG_USED_FOR_ASSERTS_ONLY = matchctx->conv_bufsiz; Datum *elems = matchctx->elems; bool *nulls = matchctx->nulls; int dims[1]; int lbs[1]; int loc; int i; /* Extract matching substrings from the original string */ loc = matchctx->next_match * matchctx->npatterns * 2; for (i = 0; i < matchctx->npatterns; i++) { int so = matchctx->match_locs[loc++]; int eo = matchctx->match_locs[loc++]; if (so < 0 || eo < 0) { elems[i] = (Datum) 0; nulls[i] = true; } else if (buf) { int len = pg_wchar2mb_with_len(matchctx->wide_str + so, buf, eo - so); Assert(len < bufsiz); elems[i] = PointerGetDatum(cstring_to_text_with_len(buf, len)); nulls[i] = false; } else { elems[i] = DirectFunctionCall3(text_substr, PointerGetDatum(matchctx->orig_str), Int32GetDatum(so + 1), Int32GetDatum(eo - so)); nulls[i] = false; } } /* And form an array */ dims[0] = matchctx->npatterns; lbs[0] = 1; /* XXX: this hardcodes assumptions about the text type */ return construct_md_array(elems, nulls, 1, dims, lbs, TEXTOID, -1, false, 'i'); }
static ArrayType * hstore_to_array_internal(HStore *hs, int ndims) { HEntry *entries = ARRPTR(hs); char *base = STRPTR(hs); int count = HS_COUNT(hs); int out_size[2] = {0, 2}; int lb[2] = {1, 1}; Datum *out_datums; bool *out_nulls; int i; Assert(ndims < 3); if (count == 0 || ndims == 0) return construct_empty_array(TEXTOID); out_size[0] = count * 2 / ndims; out_datums = palloc(sizeof(Datum) * count * 2); out_nulls = palloc(sizeof(bool) * count * 2); for (i = 0; i < count; ++i) { text *key = cstring_to_text_with_len(HS_KEY(entries, base, i), HS_KEYLEN(entries, i)); out_datums[i * 2] = PointerGetDatum(key); out_nulls[i * 2] = false; if (HS_VALISNULL(entries, i)) { out_datums[i * 2 + 1] = (Datum) 0; out_nulls[i * 2 + 1] = true; } else { text *item = cstring_to_text_with_len(HS_VAL(entries, base, i), HS_VALLEN(entries, i)); out_datums[i * 2 + 1] = PointerGetDatum(item); out_nulls[i * 2 + 1] = false; } } return construct_md_array(out_datums, out_nulls, ndims, out_size, lb, TEXTOID, -1, false, 'i'); }
static Datum PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv) { ArrayType *array; Datum rv; int i; Datum *elems; bool *nulls; int len; int lbs; Assert(plrv != Py_None); if (!PySequence_Check(plrv)) PLy_elog(ERROR, "return value of function with array return type is not a Python sequence"); len = PySequence_Length(plrv); elems = palloc(sizeof(*elems) * len); nulls = palloc(sizeof(*nulls) * len); for (i = 0; i < len; i++) { PyObject *obj = PySequence_GetItem(plrv, i); if (obj == Py_None) nulls[i] = true; else { nulls[i] = false; elems[i] = arg->elm->func(arg->elm, -1, obj); } Py_XDECREF(obj); } lbs = 1; array = construct_md_array(elems, nulls, 1, &len, &lbs, get_base_element_type(arg->typoid), arg->elm->typlen, arg->elm->typbyval, arg->elm->typalign); /* * If the result type is a domain of array, the resulting array must be * checked. */ rv = PointerGetDatum(array); if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN) domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt); return rv; }
ArrayType * create_md_guc_array(List *guc_list, int elems, int ndims) { ArrayType *array; Datum *darray; int dims[ndims]; int lbs[1]; darray = create_guc_datum_array(guc_list, elems * ndims); dims[0] = elems; dims[1] = elems; lbs[0] = 1; array = construct_md_array(darray, NULL, ndims, dims, lbs, TEXTOID, TEXT_TYPLEN, TEXT_TYPBYVAL, TEXT_TYPALIGN); pfree(darray); return array; }
Datum hstore_avals(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); Datum *d; bool *nulls; ArrayType *a; HEntry *entries = ARRPTR(hs); char *base = STRPTR(hs); int count = HS_COUNT(hs); int lb = 1; int i; if (count == 0) { a = construct_empty_array(TEXTOID); PG_RETURN_POINTER(a); } d = (Datum *) palloc(sizeof(Datum) * count); nulls = (bool *) palloc(sizeof(bool) * count); for (i = 0; i < count; ++i) { if (HS_VALISNULL(entries, i)) { d[i] = (Datum) 0; nulls[i] = true; } else { text *item = cstring_to_text_with_len(HS_VAL(entries, base, i), HS_VALLEN(entries, i)); d[i] = PointerGetDatum(item); nulls[i] = false; } } a = construct_md_array(d, nulls, 1, &count, &lb, TEXTOID, -1, false, 'i'); PG_RETURN_POINTER(a); }
static Datum PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv) { ArrayType *array; int i; Datum *elems; bool *nulls; int len; int lbs; Assert(plrv != Py_None); if (!PySequence_Check(plrv)) PLy_elog(ERROR, "return value of function with array return type is not a Python sequence"); len = PySequence_Length(plrv); elems = palloc(sizeof(*elems) * len); nulls = palloc(sizeof(*nulls) * len); for (i = 0; i < len; i++) { PyObject *obj = PySequence_GetItem(plrv, i); if (obj == Py_None) nulls[i] = true; else { nulls[i] = false; /* * We don't support arrays of row types yet, so the first argument * can be NULL. */ elems[i] = arg->elm->func(arg->elm, -1, obj); } Py_XDECREF(obj); } lbs = 1; array = construct_md_array(elems, nulls, 1, &len, &lbs, get_element_type(arg->typoid), arg->elm->typlen, arg->elm->typbyval, arg->elm->typalign); return PointerGetDatum(array); }
static Datum _Array_coerceObject(Type self, jobject objArray) { ArrayType* v; jsize idx; int lowerBound = 1; Type elemType = Type_getElementType(self); int nElems = (int)JNI_getArrayLength((jarray)objArray); Datum* values = (Datum*)palloc(nElems * sizeof(Datum) + nElems * sizeof(bool)); bool* nulls = (bool*)(values + nElems); for(idx = 0; idx < nElems; ++idx) { jobject obj = JNI_getObjectArrayElement(objArray, idx); if(obj == 0) { nulls[idx] = true; values[idx] = 0; } else { nulls[idx] = false; values[idx] = Type_coerceObject(elemType, obj); JNI_deleteLocalRef(obj); } } v = construct_md_array( values, nulls, 1, &nElems, &lowerBound, Type_getOid(elemType), Type_getLength(elemType), Type_isByValue(elemType), Type_getAlign(elemType)); pfree(values); PG_RETURN_ARRAYTYPE_P(v); }
/*! * scalar function taking an mfv sketch, returning a histogram of * its most frequent values */ Datum __mfvsketch_final(PG_FUNCTION_ARGS) { bytea * transblob = PG_GETARG_BYTEA_P(0); mfvtransval *transval = NULL; ArrayType * retval; uint32 i; int dims[2], lbs[2]; /* Oid typInput, typIOParam; */ Oid outFuncOid; bool typIsVarlena; int16 typlen; bool typbyval; char typalign; char typdelim; Oid typioparam; Oid typiofunc; if (PG_ARGISNULL(0)) PG_RETURN_NULL(); if (VARSIZE(transblob) < MFV_TRANSVAL_SZ(0)) PG_RETURN_NULL(); check_mfvtransval(transblob); transval = (mfvtransval *)VARDATA(transblob); /* * We only declare the variable-length array histo here after some sanity * checking. We risk a stack overflow otherwise. In particular, we need to * make sure that transval->max_mfvs is initialized. It might not be if the * (strict) transition function is never called. (MADLIB-254) */ Datum histo[transval->max_mfvs][2]; qsort(transval->mfvs, transval->next_mfv, sizeof(offsetcnt), cnt_cmp_desc); getTypeOutputInfo(INT8OID, &outFuncOid, &typIsVarlena); for (i = 0; i < transval->next_mfv; i++) { void *tmpp = mfv_transval_getval(transblob,i); Datum curval = PointerExtractDatum(tmpp, transval->typByVal); char *countbuf = OidOutputFunctionCall(outFuncOid, Int64GetDatum(transval->mfvs[i].cnt)); char *valbuf = OidOutputFunctionCall(transval->outFuncOid, curval); histo[i][0] = PointerGetDatum(cstring_to_text(valbuf)); histo[i][1] = PointerGetDatum(cstring_to_text(countbuf)); pfree(countbuf); pfree(valbuf); } /* * Get info about element type */ get_type_io_data(TEXTOID, IOFunc_output, &typlen, &typbyval, &typalign, &typdelim, &typioparam, &typiofunc); dims[0] = i; dims[1] = 2; lbs[0] = lbs[1] = 0; retval = construct_md_array((Datum *)histo, NULL, 2, dims, lbs, TEXTOID, -1, 0, 'i'); PG_RETURN_ARRAYTYPE_P(retval); }
static void grab_ExecutorEnd(QueryDesc * queryDesc) { Datum values[10]; bool nulls[10] = {false, false, false, false, false, false, false, false, false, false}; Relation dump_heap; RangeVar *dump_table_rv; HeapTuple tuple; Oid namespaceId; /* lookup schema */ namespaceId = GetSysCacheOid1(NAMESPACENAME, CStringGetDatum(EXTENSION_SCHEMA)); if (OidIsValid(namespaceId)) { /* lookup table */ if (OidIsValid(get_relname_relid(EXTENSION_LOG_TABLE, namespaceId))) { /* get table heap */ dump_table_rv = makeRangeVar(EXTENSION_SCHEMA, EXTENSION_LOG_TABLE, -1); dump_heap = heap_openrv(dump_table_rv, RowExclusiveLock); /* transaction info */ values[0] = Int32GetDatum(GetCurrentTransactionId()); values[1] = Int32GetDatum(GetCurrentCommandId(false)); values[2] = Int32GetDatum(MyProcPid); values[3] = Int32GetDatum(GetUserId()); /* query timing */ if (queryDesc->totaltime != NULL) { InstrEndLoop(queryDesc->totaltime); values[4] = TimestampGetDatum( TimestampTzPlusMilliseconds(GetCurrentTimestamp(), (queryDesc->totaltime->total * -1000.0))); values[5] = Float8GetDatum(queryDesc->totaltime->total); } else { nulls[4] = true; nulls[5] = true; } /* query command type */ values[6] = Int32GetDatum(queryDesc->operation); /* query text */ values[7] = CStringGetDatum( cstring_to_text(queryDesc->sourceText)); /* query params */ if (queryDesc->params != NULL) { int numParams = queryDesc->params->numParams; Oid out_func_oid, ptype; Datum pvalue; bool isvarlena; FmgrInfo *out_functions; bool arr_nulls[numParams]; size_t arr_nelems = (size_t) numParams; Datum *arr_val_elems = palloc(sizeof(Datum) * arr_nelems); Datum *arr_typ_elems = palloc(sizeof(Datum) * arr_nelems); char elem_val_byval, elem_val_align, elem_typ_byval, elem_typ_align; int16 elem_val_len, elem_typ_len; int elem_dims[1], elem_lbs[1]; int paramno; /* init */ out_functions = (FmgrInfo *) palloc( (numParams) * sizeof(FmgrInfo)); get_typlenbyvalalign(TEXTOID, &elem_val_len, &elem_val_byval, &elem_val_align); get_typlenbyvalalign(REGTYPEOID, &elem_typ_len, &elem_typ_byval, &elem_typ_align); elem_dims[0] = arr_nelems; elem_lbs[0] = 1; for (paramno = 0; paramno < numParams; paramno++) { pvalue = queryDesc->params->params[paramno].value; ptype = queryDesc->params->params[paramno].ptype; getTypeOutputInfo(ptype, &out_func_oid, &isvarlena); fmgr_info(out_func_oid, &out_functions[paramno]); arr_typ_elems[paramno] = ptype; arr_nulls[paramno] = true; if (!queryDesc->params->params[paramno].isnull) { arr_nulls[paramno] = false; arr_val_elems[paramno] = PointerGetDatum( cstring_to_text( OutputFunctionCall(&out_functions[paramno], pvalue))); } } values[8] = PointerGetDatum( construct_md_array( arr_val_elems, arr_nulls, 1, elem_dims, elem_lbs, TEXTOID, elem_val_len, elem_val_byval, elem_val_align)); values[9] = PointerGetDatum( construct_array( arr_typ_elems, arr_nelems, REGTYPEOID, elem_typ_len, elem_typ_byval, elem_typ_align)); pfree(out_functions); pfree(arr_val_elems); } else { nulls[8] = true; nulls[9] = true; } /* insert */ tuple = heap_form_tuple(dump_heap->rd_att, values, nulls); simple_heap_insert(dump_heap, tuple); heap_close(dump_heap, RowExclusiveLock); } } if (prev_ExecutorEnd) prev_ExecutorEnd(queryDesc); else standard_ExecutorEnd(queryDesc); }
static PyObj array_item(PyObj self, Py_ssize_t item) { volatile PyObj rob = NULL; PyPgTypeInfo typinfo, atypinfo; ArrayType *at; Datum rd; bool isnull = false; int index = (int) item; PyObj elm; elm = PyPgType_GetElementType(Py_TYPE(self)); typinfo = PyPgTypeInfo(elm); atypinfo = PyPgTypeInfo(Py_TYPE(self)); at = DatumGetArrayTypeP(PyPgObject_GetDatum(self)); /* convert index */ ++index; if (ARR_NDIM(at) == 0) { PyErr_SetString(PyExc_IndexError, "empty array"); return(NULL); } /* * Note that the comparison is '>', not '>='. */ if (index > ARR_DIMS(at)[0]) { PyErr_Format(PyExc_IndexError, "index %d out of range %d", item, ARR_DIMS(at)[0]); return(NULL); } /* * Single dimenion array? Get an element. */ if (ARR_NDIM(at) == 1) { PG_TRY(); { rd = array_ref(at, 1, &index, atypinfo->typlen, typinfo->typlen, typinfo->typbyval, typinfo->typalign, &isnull); if (isnull) { rob = Py_None; Py_INCREF(rob); } else { /* * It points into the array structure, so there's no need to free. */ rob = PyPgObject_New(elm, rd); } } PG_CATCH(); { Py_XDECREF(rob); rob = NULL; PyErr_SetPgError(false); return(NULL); } PG_END_TRY(); } else { ArrayType *rat; int lower[MAXDIM] = {index,0,}; int upper[MAXDIM] = {index,0,}; /* * Multiple dimensions, so get a slice. */ PG_TRY(); { ArrayType *xat; Datum *elements; bool *nulls; int nelems; int ndims, i; int lbs[MAXDIM]; int dims[MAXDIM]; xat = array_get_slice(at, 1, upper, lower, atypinfo->typlen, typinfo->typlen, typinfo->typbyval, typinfo->typalign); /* * Eventually, this should probably be changed to change the already * allocated ArrayType at 'xat', but for now use the available * interfaces for creating the expected result. */ deconstruct_array(xat, typinfo->typoid, typinfo->typlen, typinfo->typbyval, typinfo->typalign, &elements, &nulls, &nelems ); /* * Alter dims, lbs, and ndims: we are removing the first dimension. */ ndims = ARR_NDIM(xat); for (i = 1; i < ndims; ++i) lbs[i-1] = ARR_LBOUND(xat)[i]; for (i = 1; i < ndims; ++i) dims[i-1] = ARR_DIMS(xat)[i]; --ndims; /* * Construct the expected result to a Python itemget call. */ rat = construct_md_array(elements, nulls, ndims, dims, lbs, typinfo->typoid, typinfo->typlen, typinfo->typbyval, typinfo->typalign); pfree(elements); pfree(nulls); pfree(xat); rob = PyPgObject_New(Py_TYPE(self), PointerGetDatum(rat)); pfree(rat); } PG_CATCH(); { PyErr_SetPgError(false); return(NULL); } PG_END_TRY(); } return(rob); }
/* * array_from_list - given an element type and a list(), build an array * using the described structure. * * Sets a Python error and returns NULL on failure. */ static ArrayType * array_from_list_and_info(PyObj element_type, PyObj listob, int elemmod, int ndims, int *dims, int *lbs) { PyPgTypeInfo typinfo = PyPgTypeInfo(element_type); unsigned int nelems; int i; Datum * volatile datums = NULL; bool * volatile nulls = NULL; ArrayType * volatile rat = NULL; Assert(PyList_CheckExact(listob)); nelems = PyList_GET_SIZE(listob); PG_TRY(); { /* * palloc0 as cleanup in the PG_CATCH() will depend on this. */ nulls = palloc0(sizeof(bool) * nelems); datums = palloc0(sizeof(Datum) * nelems); for (i = 0; i < nelems; ++i) { PyPgType_DatumNew(element_type, PyList_GET_ITEM(listob, i), elemmod, (Datum *) &(datums[i]), (bool *) &(nulls[i])); } /* * Everything has been allocated, make the array. */ rat = construct_md_array( (Datum *) datums, (bool *) nulls, ndims, dims, lbs, typinfo->typoid, typinfo->typlen, typinfo->typbyval, typinfo->typalign); /* * Cleanup. */ if (!typinfo->typbyval) { for (i = 0; i < nelems; ++i) { /* * Array construction completed successfully, * so go over the entire array of datums. */ if (!nulls[i]) pfree(DatumGetPointer(datums[i])); } } pfree((bool *) nulls); pfree((Datum *) datums); } PG_CATCH(); { /* * Try and cleanup as much memory as possible. * * Currently, this code will run in the procedure context, * so whatever leaks here will remain allocated for the duration of the * procedure. If failure is often the part of a loop, the leaks could * be problematic. */ if (rat != NULL) { /* * When rat != NULL, failure occurred after the array * was built, which means it had trouble freeing the resources. * Attempt to free rat, but leave it at that. */ pfree((char *) rat); } else { if (datums != NULL && nulls != NULL) { if (!typinfo->typbyval) { /* * This is a bit different from the non-error case; * rather than pfree'ing everything, we watch for * NULL pointers.. */ for (i = 0; i < nelems; ++i) { char *p = DatumGetPointer(datums[i]); if (nulls[i]) continue; if (PointerIsValid(p)) pfree(p); else break; } } } if (datums != NULL) pfree((Datum *) datums); if (nulls != NULL) pfree((bool *) nulls); } PyErr_SetPgError(false); rat = NULL; } PG_END_TRY(); return((ArrayType *) rat); }
/* * array_from_py_list - given an element type and a list(), build an array */ static ArrayType * array_from_py_list(PyObj element_type, PyObj listob, int elemmod) { PyPgTypeInfo typinfo = PyPgTypeInfo(element_type); Datum * volatile datums = NULL; bool * volatile nulls = NULL; unsigned int nelems; int i, ndims; int dims[MAXDIM]; int lbs[MAXDIM]; ArrayType *rat = NULL; ndims = py_list_dimensions(listob, dims); Assert(ndims <= MAXDIM); /* * From the dimensions, calculate the expected number of elements. * At this point it is not known if the array is balanced */ nelems = dims[ndims-1]; for (i = ndims-2; i > -1; --i) { unsigned int n = nelems * dims[i]; if (n < nelems) { elog(ERROR, "too many elements for array"); } nelems = n; } if (nelems == 0 && ndims > 1) elog(ERROR, "malformed nesting of list objects"); PG_TRY(); { /* * palloc0 as cleanup in the PG_CATCH() will depend on this. */ nulls = palloc0(sizeof(bool) * nelems); datums = palloc0(sizeof(Datum) * nelems); /* * elog's on failure, this will validate the balance/sizes of the * dimensions. */ fill_elements(element_type, listob, elemmod, nelems, ndims, dims, (Datum *) datums, (bool *) nulls); /* * Arrays built from lists don't support custom lower bounds, * so initialize it to the default '1'. */ for (i = 0; i < ndims; ++i) lbs[i] = 1; /* * Everything has been allocated, make the array. */ rat = construct_md_array( (Datum *) datums, (bool *) nulls, ndims, dims, lbs, typinfo->typoid, typinfo->typlen, typinfo->typbyval, typinfo->typalign); /* * Cleanup. */ if (!typinfo->typbyval) { for (i = 0; i < nelems; ++i) { /* * Array construction completed successfully, * so go over the entire array of datums. */ if (!nulls[i]) pfree(DatumGetPointer(datums[i])); } } pfree((bool *) nulls); pfree((Datum *) datums); } PG_CATCH(); { /* * Try and cleanup as much memory as possible. * * Currently, this code will run in the procedure context, * so whatever leaks here will remain allocated for the duration of the * procedure. */ if (rat != NULL) { /* * When rat != NULL, failure occurred after the array * was built, which means it had trouble freeing the resources. * Attempt to free rat, but leave it at that. */ pfree(rat); } else { if (datums != NULL && nulls != NULL) { if (!typinfo->typbyval) { /* * This is a bit different from the non-error case; * rather than pfree'ing everything, we watch for * NULL pointers.. */ for (i = 0; i < nelems; ++i) { char *p = DatumGetPointer(datums[i]); if (nulls[i]) continue; if (PointerIsValid(p)) pfree(p); else break; } } } if (datums != NULL) pfree((Datum *) datums); if (nulls != NULL) pfree((bool *) nulls); } PG_RE_THROW(); } PG_END_TRY(); return(rat); }
static void FunctionParserInit(FunctionParser *self, Checker *checker, const char *infile, TupleDesc desc, bool multi_process, Oid collation) { int i; ParsedFunction function; int nargs; Oid funcid; HeapTuple ftup; Form_pg_proc pp; bool tupledesc_matched = false; if (pg_strcasecmp(infile, "stdin") == 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("cannot load from STDIN in the case of \"TYPE = FUNCTION\""))); if (checker->encoding != -1) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("does not support parameter \"ENCODING\" in \"TYPE = FUNCTION\""))); function = ParseFunction(infile, false); funcid = function.oid; fmgr_info(funcid, &self->flinfo); if (!self->flinfo.fn_retset) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function must return set"))); ftup = SearchSysCache(PROCOID, ObjectIdGetDatum(funcid), 0, 0, 0); pp = (Form_pg_proc) GETSTRUCT(ftup); /* Check data type of the function result value */ if (pp->prorettype == desc->tdtypeid && desc->tdtypeid != RECORDOID) tupledesc_matched = true; else if (pp->prorettype == RECORDOID) { TupleDesc resultDesc = NULL; /* Check for OUT parameters defining a RECORD result */ resultDesc = build_function_result_tupdesc_t(ftup); if (resultDesc) { tupledesc_match(desc, resultDesc); tupledesc_matched = true; FreeTupleDesc(resultDesc); } } else if (get_typtype(pp->prorettype) != TYPTYPE_COMPOSITE) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("function return data type and target table data type do not match"))); if (tupledesc_matched && checker->tchecker) checker->tchecker->status = NO_COERCION; /* * assign arguments */ nargs = function.nargs; for (i = 0; #if PG_VERSION_NUM >= 80400 i < nargs - function.nvargs; #else i < nargs; #endif ++i) { if (function.args[i] == NULL) { if (self->flinfo.fn_strict) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("function is strict, but argument %d is NULL", i))); self->fcinfo.argnull[i] = true; } else { Oid typinput; Oid typioparam; getTypeInputInfo(pp->proargtypes.values[i], &typinput, &typioparam); self->fcinfo.arg[i] = OidInputFunctionCall(typinput, (char *) function.args[i], typioparam, -1); self->fcinfo.argnull[i] = false; pfree(function.args[i]); } } /* * assign variadic arguments */ #if PG_VERSION_NUM >= 80400 if (function.nvargs > 0) { int nfixedarg; Oid func; Oid element_type; int16 elmlen; bool elmbyval; char elmalign; char elmdelim; Oid elmioparam; Datum *elems; bool *nulls; int dims[1]; int lbs[1]; ArrayType *arry; nfixedarg = i; element_type = pp->provariadic; /* * Get info about element type, including its input conversion proc */ get_type_io_data(element_type, IOFunc_input, &elmlen, &elmbyval, &elmalign, &elmdelim, &elmioparam, &func); elems = (Datum *) palloc(function.nvargs * sizeof(Datum)); nulls = (bool *) palloc0(function.nvargs * sizeof(bool)); for (i = 0; i < function.nvargs; i++) { if (function.args[nfixedarg + i] == NULL) nulls[i] = true; else { elems[i] = OidInputFunctionCall(func, (char *) function.args[nfixedarg + i], elmioparam, -1); pfree(function.args[nfixedarg + i]); } } dims[0] = function.nvargs; lbs[0] = 1; arry = construct_md_array(elems, nulls, 1, dims, lbs, element_type, elmlen, elmbyval, elmalign); self->fcinfo.arg[nfixedarg] = PointerGetDatum(arry); } /* * assign default arguments */ if (function.ndargs > 0) { Datum proargdefaults; bool isnull; char *str; List *defaults; int ndelete; ListCell *l; /* shouldn't happen, FuncnameGetCandidates messed up */ if (function.ndargs > pp->pronargdefaults) elog(ERROR, "not enough default arguments"); proargdefaults = SysCacheGetAttr(PROCOID, ftup, Anum_pg_proc_proargdefaults, &isnull); Assert(!isnull); str = TextDatumGetCString(proargdefaults); defaults = (List *) stringToNode(str); Assert(IsA(defaults, List)); pfree(str); /* Delete any unused defaults from the returned list */ ndelete = list_length(defaults) - function.ndargs; while (ndelete-- > 0) defaults = list_delete_first(defaults); self->arg_econtext = CreateStandaloneExprContext(); foreach(l, defaults) { Expr *expr = (Expr *) lfirst(l); ExprState *argstate; ExprDoneCond thisArgIsDone; /* probably shouldn't happen ... */ if (nargs >= FUNC_MAX_ARGS) ereport(ERROR, (errcode(ERRCODE_TOO_MANY_ARGUMENTS), errmsg("cannot pass more than %d arguments to a function", FUNC_MAX_ARGS))); argstate = ExecInitExpr(expr, NULL); self->fcinfo.arg[nargs] = ExecEvalExpr(argstate, self->arg_econtext, &self->fcinfo.argnull[nargs], &thisArgIsDone); if (thisArgIsDone != ExprSingleResult) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("functions and operators can take at most one set argument"))); nargs++; }
Datum alpine_miner_nn_ca_change(PG_FUNCTION_ARGS) { ArrayType *weight_arg, *columns_arg, *input_range_arg, *input_base_arg,*hidden_node_number_arg, *result; Datum *weight_data, *columns_data, *input_range_data, *input_base_data, *hidden_node_number_data, *result_data; bool *weight_nulls, *columns_nulls, *input_range_nulls, *input_base_nulls, *hidden_node_number_nulls,*result_nulls; int weight_count, columns_count, input_range_count, input_base_count, hidden_node_number_count,result_count ; Oid result_eltype; int16 result_typlen; bool result_typbyval; char result_typalign; double output_range_arg,output_base_arg, learning_rate_ar, label_arg; int hidden_layer_number_arg, output_node_no_arg, set_size_arg; bool normalize_arg, numerical_label_arg ; int ndims, *dims, *lbs; int i; int j; int k; int all_hidden_node_count; int weight_index; int hidden_node_number_index = 0; bool null_data; double * input; double * output; int * hidden_node_number; double *weight; double *hidden_node_output; double delta = 0.0; double total_error = 0.0; double * output_error; double direct_output_error = 0.0; double * hidden_node_error; double error_sum = 0.0; double current_change = 0.0; double threshold_change = 0.0; if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3) || PG_ARGISNULL(4) || PG_ARGISNULL(5) || PG_ARGISNULL(6) || PG_ARGISNULL(7) || PG_ARGISNULL(8) || PG_ARGISNULL(9) || PG_ARGISNULL(10) || PG_ARGISNULL(11) || PG_ARGISNULL(12)){ PG_RETURN_NULL(); } /* get weight_arg args */ weight_arg = PG_GETARG_ARRAYTYPE_P(0); null_data = alpine_miner_deconstruct_array(weight_arg, &weight_data, &weight_nulls,&weight_count); if (null_data) { PG_RETURN_NULL(); } columns_arg = PG_GETARG_ARRAYTYPE_P(1); null_data = alpine_miner_deconstruct_array(columns_arg, &columns_data, &columns_nulls,&columns_count); if (null_data) { PG_RETURN_NULL(); } /* get input_range_arg args */ input_range_arg = PG_GETARG_ARRAYTYPE_P(2); null_data = alpine_miner_deconstruct_array(input_range_arg, &input_range_data, &input_range_nulls,&input_range_count); if (null_data) { PG_RETURN_NULL(); } /* get input_base_arg args */ input_base_arg = PG_GETARG_ARRAYTYPE_P(3); null_data = alpine_miner_deconstruct_array(input_base_arg, &input_base_data, &input_base_nulls,&input_base_count); if (null_data) { PG_RETURN_NULL(); } /* get hidden_node_number_arg args */ hidden_node_number_arg = PG_GETARG_ARRAYTYPE_P(4); null_data = alpine_miner_deconstruct_array(hidden_node_number_arg, &hidden_node_number_data, &hidden_node_number_nulls,&hidden_node_number_count); if (null_data) { PG_RETURN_NULL(); } hidden_layer_number_arg= PG_GETARG_INT32(5); output_range_arg = PG_GETARG_FLOAT8(6); output_base_arg = PG_GETARG_FLOAT8(7); output_node_no_arg = PG_GETARG_INT32(8); normalize_arg = PG_GETARG_BOOL(9); numerical_label_arg = PG_GETARG_BOOL(10); label_arg = PG_GETARG_FLOAT8(11); set_size_arg = PG_GETARG_INT32(12); if (set_size_arg <= 0) { set_size_arg = 1; } #ifdef ALPINE_DEBUG elog(WARNING,"%f",DatumGetFloat8(columns_data[0])); #endif input = (double*)palloc(columns_count * sizeof(double));; output = (double*)palloc(output_node_no_arg * sizeof(double)); hidden_node_number = (int*) palloc(hidden_node_number_count * sizeof(int)); weight = (double*)palloc(weight_count * sizeof(double)); for (i = 0; i < weight_count; i++) { weight[i] = DatumGetFloat8(weight_data[i]); } all_hidden_node_count = 0; for (i = 0; i < hidden_layer_number_arg; i++) { hidden_node_number[i] = DatumGetInt32(hidden_node_number_data[i]); all_hidden_node_count += hidden_node_number[i]; } hidden_node_output = (double*)palloc(all_hidden_node_count * sizeof(double)); //caculate input if (normalize_arg) { i = 0; while (i < columns_count) { if (DatumGetFloat8(input_range_data[i]) != 0) { input[i] = ((DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i]))/DatumGetFloat8(input_range_data[i])); } else { input[i] = (DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i])); } #ifdef ALPINE_DEBUG elog(WARNING, "input:%f", input[i]); #endif i = i + 1; } } else { i = 0; while (i < columns_count) { input[i] = DatumGetFloat8(columns_data[i]); i = i + 1; } } // caculate hidden node output of 1st layer i = 0; while (i < hidden_node_number[0]) { hidden_node_output[i] = weight[0+i*(columns_count + 1)]; j = 0; while (j < columns_count) { hidden_node_output[i] = hidden_node_output[i]+input[j]*weight[1 + j + i *(columns_count + 1)]; #ifdef ALPINE_DEBUG elog(WARNING,"hiddensum[%d] input[%d] %f weight[%d] %f", i, j,input[j] , 1+j +(i)*(columns_count +1), weight[1+j +i*(columns_count + 1)]); #endif j = j + 1; } if (hidden_node_output[i] < -45.0) { hidden_node_output[i] = 0; } else if (hidden_node_output[i] > 45.0) { hidden_node_output[i] = 1; } else { hidden_node_output[i] = (1.0/(1.0+exp( -1.0 * hidden_node_output[i]))); } #ifdef ALPINE_DEBUG elog(WARNING,"hidden[%d] %f", i, hidden_node_output[i]); #endif i = i + 1; } // calculate hidden layer 2~last output weight_index = hidden_node_number[0] * (columns_count + 1) ; if (hidden_layer_number_arg > 1) { hidden_node_number_index = 0; i = 1; while (i < hidden_layer_number_arg ) { hidden_node_number_index = hidden_node_number_index + hidden_node_number[i - 1]; j = 0; while (j < hidden_node_number[i]) { hidden_node_output[hidden_node_number_index + j] = weight[weight_index + (hidden_node_number[i - 1] +1) * j]; k = 0; while (k < hidden_node_number[i - 1]) { hidden_node_output[hidden_node_number_index + j] = hidden_node_output[hidden_node_number_index + j]+hidden_node_output[hidden_node_number_index - hidden_node_number[i - 1] + k]*weight[weight_index + (hidden_node_number[i - 1] +1) * j + k + 1]; k = k + 1; } if (hidden_node_output[hidden_node_number_index + j] < -45.0) { hidden_node_output[hidden_node_number_index + j] = 0; } else if (hidden_node_output[hidden_node_number_index + j] > 45.0) { hidden_node_output[hidden_node_number_index + j] = 1; } else { hidden_node_output[hidden_node_number_index + j] = (1.0/(1+exp(-1.0*hidden_node_output[hidden_node_number_index+j]))); } j = j + 1; } weight_index = weight_index + hidden_node_number[i] * (hidden_node_number[i - 1] + 1); i = i + 1; } } //compute output value of output node; i = 0; while (i < output_node_no_arg) { output[i] = weight[weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i]; #ifdef ALPINE_DEBUG elog(WARNING,"weightindex:%d,weight[%d] %f",weight_index, weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i, output[i]); #endif j = 0; while (j < hidden_node_number[hidden_layer_number_arg-1]) { #ifdef ALPINE_DEBUG elog(WARNING,"ouput[%d]:%f ,hidden_node_number_index:%d,j:%d, weight[%d]:%f",i,output[i], hidden_node_number_index ,j,1+j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i , weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ]); #endif output[i] = output[i]+hidden_node_output[hidden_node_number_index + j] * weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ]; j = j + 1; } #ifdef ALPINE_DEBUG elog(WARNING,"ouputsum[%d] %f", i, output[i]); #endif if (numerical_label_arg) { output[i] = ((output[i]) * output_range_arg+output_base_arg); #ifdef ALPINE_DEBUG elog(WARNING,"output:%f, %f,%f",output[i],output_range_arg,output_base_arg); #endif } else { if (output[i] < -45.0) { output[i] = 0; } else if (output[i] > 45.0) { output[i] = 1; } else { output[i] = (1.0/(1+exp(-1.0*output[i]))); } } #ifdef ALPINE_DEBUG elog(WARNING,"ouputsum2[%d] %f", i, output[i]); #endif i = i + 1; } /* get output array element type */ result_eltype = FLOAT8OID; get_typlenbyvalalign(result_eltype, &result_typlen, &result_typbyval, &result_typalign); /* construct result array */ result_count = weight_count + 1; result_data = (Datum *)palloc(result_count * sizeof(Datum)); result_nulls = (bool *)palloc(result_count * sizeof(bool)); for (i = 0; i < result_count; i++) { result_nulls[i] = false; } //compute error of output node output_error = (double *)palloc(output_node_no_arg * sizeof(double)); for(i = 0; i < output_node_no_arg; i++) { if(numerical_label_arg) { if (output_range_arg == 0.0) { direct_output_error = 0.0; } else { direct_output_error = (label_arg - output[i])/output_range_arg; } output_error[i] = direct_output_error; } else { if (((int)label_arg) == i) { direct_output_error = 1.0 - output[i]; } else { direct_output_error = 0.0 - output[i]; } #ifdef ALPINE_DEBUG elog(WARNING,"label_arg :%f %d %d", label_arg, i, (((int)label_arg) == i)); #endif output_error[i] = direct_output_error * output[i] * (1- output[i]); } total_error += direct_output_error*direct_output_error; #ifdef ALPINE_DEBUG elog(WARNING,"output_error[%d] %f totalerror:%f", i, output_error[i], total_error); #endif } //compute hidden_node_error of last layer hidden_node---- hidden_node_error = (double*)palloc(all_hidden_node_count * sizeof(double)); weight_index = weight_count - output_node_no_arg*(hidden_node_number[hidden_layer_number_arg - 1] + 1) ; hidden_node_number_index = all_hidden_node_count - hidden_node_number[hidden_layer_number_arg - 1]; for(i = 0; i < hidden_node_number[hidden_layer_number_arg - 1]; i++) { error_sum = 0.0; for(k = 0; k < output_node_no_arg; k++) { error_sum = error_sum+output_error[k]*weight[weight_index + (hidden_node_number[hidden_layer_number_arg - 1] + 1)*k + i + 1]; #ifdef ALPINE_DEBUG elog(WARNING,"output_error[%d]:%f,weight[%d]:%f",k,output_error[k],weight_index + (hidden_node_number[hidden_layer_number_arg - 1] + 1)*k + i + 1, weight[weight_index + (hidden_node_number[hidden_layer_number_arg - 1] + 1)*k + i + 1]); #endif } hidden_node_error[hidden_node_number_index + i] = error_sum*hidden_node_output[hidden_node_number_index + i]*(1.0-hidden_node_output[hidden_node_number_index + i]); #ifdef ALPINE_DEBUG elog(WARNING,"hidden_node_error[%d] %f ", hidden_node_number_index+i, hidden_node_error[hidden_node_number_index + i]); #endif } //compute hidden_node_error of 1 layer to the one before last layer hidden node if (hidden_layer_number_arg > 1) { weight_index = weight_index - (hidden_node_number[hidden_layer_number_arg - 2] + 1)*hidden_node_number[hidden_layer_number_arg - 1]; hidden_node_number_index = hidden_node_number_index - hidden_node_number[hidden_layer_number_arg - 2]; for(i = hidden_layer_number_arg - 2; i >= 0; i--) { for(j = 0; j < hidden_node_number[i]; j++) { error_sum = 0.0; for (k = 0; k < hidden_node_number[i + 1]; k++) { error_sum = error_sum+hidden_node_error[hidden_node_number_index + hidden_node_number[i] + k]*weight[weight_index + (hidden_node_number[i]+1)*(k) + j + 1]; #ifdef ALPINE_DEBUG elog(WARNING,"i:%d j:%d k:%d; hidden_node_error[%d]:%f,weight[%d]:%f",i,j,k,hidden_node_number_index + hidden_node_number[i] + k, hidden_node_error[hidden_node_number_index + hidden_node_number[i] + k], weight_index + (hidden_node_number[i]+1)*(k) + j + 1,weight[weight_index + (hidden_node_number[i]+1)*(k) + j + 1]); #endif } hidden_node_error[hidden_node_number_index + j] = error_sum*hidden_node_output[hidden_node_number_index + j]*(1-hidden_node_output[hidden_node_number_index + j]); #ifdef ALPINE_DEBUG elog(WARNING,"hidden_node_error[%d] %f ", hidden_node_number_index+j, hidden_node_error[hidden_node_number_index + j]); #endif } weight_index = weight_index - (hidden_node_number[i - 1]+1) * hidden_node_number[i]; hidden_node_number_index = hidden_node_number_index - hidden_node_number[i - 1]; } } //compute weight change of output node weight_index = weight_count - (hidden_node_number[hidden_layer_number_arg - 1]+ 1)* output_node_no_arg; hidden_node_number_index = all_hidden_node_count - hidden_node_number[hidden_layer_number_arg - 1]; for(i = 0; i < output_node_no_arg; i++) { delta = 1.0/set_size_arg*output_error[i]; threshold_change = delta; result_data[weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i)] = Float8GetDatum(threshold_change); #ifdef ALPINE_DEBUG elog(WARNING, " result_data [%d] %f ", weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i), threshold_change); #endif for(j = 0; j < hidden_node_number[hidden_layer_number_arg - 1] ; j++) { current_change = delta * hidden_node_output[hidden_node_number_index + j]; result_data[weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i) + 1 +j] = Float8GetDatum(current_change); #ifdef ALPINE_DEBUG elog(WARNING, " result_data [%d] %f , i:%d j:%d output_error[%d]:%f, hidden_node_output[%d]:%f", weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i) + 1+ j, current_change, i,j,i,output_error[i],hidden_node_number_index + j, hidden_node_output[hidden_node_number_index + j]); #endif } } //compute weight change of hidden node last layer to 2 layer if (hidden_layer_number_arg > 1) { for(i = hidden_layer_number_arg - 1; i >= 1; i--) { weight_index = weight_index - (hidden_node_number[i - 1]+1)*hidden_node_number[i]; hidden_node_number_index = hidden_node_number_index - hidden_node_number[i - 1]; delta = 0.0; for (j = 0; j < hidden_node_number[i]; j++) { delta = (1.0/set_size_arg*hidden_node_error[hidden_node_number_index + hidden_node_number[i - 1] + j]); threshold_change = delta; result_data[weight_index + (hidden_node_number[i - 1] + 1) * (j)] = Float8GetDatum(threshold_change); #ifdef ALPINE_DEBUG elog(WARNING, " result_data [%d] %f ", weight_index + (hidden_node_number[i - 1] + 1) * (j), threshold_change); #endif for(k = 0; k < hidden_node_number[i - 1]; k++) { current_change = delta * hidden_node_output[hidden_node_number_index + k]; result_data[weight_index + (hidden_node_number[i - 1] + 1) * (j) + 1 + k] = Float8GetDatum(current_change); #ifdef ALPINE_DEBUG elog(WARNING, " result_data [%d] %f i:%d, j:%d k:%d hidden_node_error[%d]:%f hidden_node_output[%d]:%f", weight_index + (hidden_node_number[i - 1] + 1) * (j) + 1 + k, current_change,i,j,k,hidden_node_number_index + hidden_node_number[i - 1] + j, hidden_node_error[hidden_node_number_index + hidden_node_number[i - 1] + j], hidden_node_number_index + k,hidden_node_output[hidden_node_number_index + k]); #endif } } } } //compute weight change of first layer hidden node weight_index = 0; hidden_node_number_index = 0; delta = 0.0; for(j = 0; j < hidden_node_number[0]; j++) { delta = 1.0/set_size_arg*hidden_node_error[hidden_node_number_index + j]; threshold_change = delta; result_data[weight_index + (columns_count+1)*(j)] = Float8GetDatum(threshold_change); #ifdef ALPINE_DEBUG elog(WARNING, " result_data [%d] %f ", weight_index + (columns_count+1)*(j), threshold_change); #endif for(k = 0; k < columns_count; k++) { current_change = delta*input[k]; result_data[weight_index + (columns_count+1)*(j) + k + 1] = Float8GetDatum(current_change); #ifdef ALPINE_DEBUG elog(WARNING, " result_data [%d] %f j:%d k:%d hidden_node_error[%d]:%f input[%d]:%f", weight_index + (columns_count+1)*(j) + k + 1, current_change,j,k,hidden_node_number_index + j, hidden_node_error[hidden_node_number_index + j], k, input[k]); #endif } } result_data[weight_count] = Float8GetDatum(total_error); ndims = 1; dims = (int *) palloc(sizeof(int)); dims[0] = result_count; lbs = (int *) palloc(sizeof(int)); lbs[0] = 1; result = construct_md_array((void *)result_data, result_nulls, ndims, dims, lbs, result_eltype, result_typlen, result_typbyval, result_typalign); // pfree(result); pfree(weight_data); pfree(columns_data); pfree(input_range_data); pfree(input_base_data); pfree(hidden_node_number_data); pfree(result_data); pfree(weight_nulls); pfree(columns_nulls); pfree(input_range_nulls); pfree(input_base_nulls); pfree(hidden_node_number_nulls); pfree(result_nulls); pfree(input); pfree(output); pfree(lbs); pfree(dims); pfree(hidden_node_output); pfree(weight); pfree(hidden_node_number); pfree(hidden_node_error); pfree(output_error); PG_RETURN_ARRAYTYPE_P(result); }
Datum pseudoinverse(PG_FUNCTION_ARGS) { /* * A note on types: PostgreSQL array dimensions are of type int. See, e.g., * the macro definition ARR_DIMS */ int rows, columns; float8 *A, *Aplus; ArrayType *A_PG, *Aplus_PG; int lbs[2], dims[2]; /* * Perform all the error checking needed to ensure that no one is * trying to call this in some sort of crazy way. */ if (PG_NARGS() != 1) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("pseudoinverse called with %d arguments", PG_NARGS()))); } if (PG_ARGISNULL(0)) PG_RETURN_NULL(); A_PG = PG_GETARG_ARRAYTYPE_P(0); if (ARR_ELEMTYPE(A_PG) != FLOAT8OID) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("pseudoinverse only defined over float8[]"))); if (ARR_NDIM(A_PG) != 2) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("pseudoinverse only defined over 2 dimensional arrays")) ); if (ARR_NULLBITMAP(A_PG)) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("null array element not allowed in this context"))); /* Extract rows, columns, and data */ rows = ARR_DIMS(A_PG)[0]; columns = ARR_DIMS(A_PG)[1]; A = (float8 *) ARR_DATA_PTR(A_PG); /* Allocate a PG array for the result, "Aplus" is A+, the pseudo inverse of A */ lbs[0] = 1; lbs[1] = 1; dims[0] = columns; dims[1] = rows; Aplus_PG = construct_md_array(NULL, NULL, 2, dims, lbs, FLOAT8OID, sizeof(float8), true, 'd'); Aplus = (float8 *) ARR_DATA_PTR(Aplus_PG); pinv(rows,columns,A,Aplus); PG_RETURN_ARRAYTYPE_P(Aplus_PG); }
Datum array_multi_index( PG_FUNCTION_ARGS ) { if( PG_ARGISNULL(0) ) { PG_RETURN_NULL(); } if( PG_ARGISNULL(1) ) { PG_RETURN_NULL(); } ArrayType* values = PG_GETARG_ARRAYTYPE_P( 0 ); ArrayType* indices = PG_GETARG_ARRAYTYPE_P( 1 ); Oid values_type = ARR_ELEMTYPE( values ); int16 values_width; bool values_passbyvalue; char values_alignmentcode; Datum* values_content; bool* values_nullflags; int values_length; get_typlenbyvalalign( values_type, &values_width, &values_passbyvalue, &values_alignmentcode ); deconstruct_array( values, values_type, values_width, values_passbyvalue, values_alignmentcode, &values_content, &values_nullflags, &values_length ); Oid indices_type = ARR_ELEMTYPE( indices ); int16 indices_width; bool indices_passbyvalue; char indices_alignmentcode; Datum* indices_content; bool* indices_nullflags; int indices_length; get_typlenbyvalalign( indices_type, &indices_width, &indices_passbyvalue, &indices_alignmentcode ); deconstruct_array( indices, indices_type, indices_width, indices_passbyvalue, indices_alignmentcode, &indices_content, &indices_nullflags, &indices_length ); Oid results_type = values_type; int16 results_width = values_width; bool results_passbyvalue = values_passbyvalue; char results_alignmentcode = values_alignmentcode; Datum* results_content = (Datum *)palloc( sizeof(Datum) * indices_length ); bool* results_nullflags = (bool *)palloc0( sizeof(bool) * indices_length ); int results_length = indices_length; int i; for( i = 0; i < indices_length; ++i ) { if( indices_nullflags[i] ) { results_content[i] = 0; results_nullflags[i] = true; } else if( indices_content[i] - 1 >= (long unsigned)values_length ) { results_content[i] = 0; results_nullflags[i] = true; } else { results_content[i] = values_content[ indices_content[i] - 1 ]; results_nullflags[i] = values_nullflags[ indices_content[i] - 1 ]; } } int dims[1]; int lbs[1]; dims[0] = results_length; lbs[0] = 1; ArrayType* results = construct_md_array( results_content, results_nullflags, 1, dims, lbs, results_type, results_width, results_passbyvalue, results_alignmentcode ); pfree( results_content ); pfree( results_nullflags ); PG_RETURN_ARRAYTYPE_P( results ); }
/* * Convert Python sequence to SQL array. */ static Datum PLySequence_ToArray(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray) { ArrayType *array; int i; Datum *elems; bool *nulls; int64 len; int ndim; int dims[MAXDIM]; int lbs[MAXDIM]; int currelem; PyObject *pyptr = plrv; PyObject *next; if (plrv == Py_None) { *isnull = true; return (Datum) 0; } *isnull = false; /* * Determine the number of dimensions, and their sizes. */ ndim = 0; len = 1; Py_INCREF(plrv); for (;;) { if (!PyList_Check(pyptr)) break; if (ndim == MAXDIM) PLy_elog(ERROR, "number of array dimensions exceeds the maximum allowed (%d)", MAXDIM); dims[ndim] = PySequence_Length(pyptr); if (dims[ndim] < 0) PLy_elog(ERROR, "could not determine sequence length for function return value"); if (dims[ndim] > MaxAllocSize) PLy_elog(ERROR, "array size exceeds the maximum allowed"); len *= dims[ndim]; if (len > MaxAllocSize) PLy_elog(ERROR, "array size exceeds the maximum allowed"); if (dims[ndim] == 0) { /* empty sequence */ break; } ndim++; next = PySequence_GetItem(pyptr, 0); Py_XDECREF(pyptr); pyptr = next; } Py_XDECREF(pyptr); /* * Check for zero dimensions. This happens if the object is a tuple or a * string, rather than a list, or is not a sequence at all. We don't map * tuples or strings to arrays in general, but in the first level, be * lenient, for historical reasons. So if the object is a sequence of any * kind, treat it as a one-dimensional array. */ if (ndim == 0) { if (!PySequence_Check(plrv)) PLy_elog(ERROR, "return value of function with array return type is not a Python sequence"); ndim = 1; len = dims[0] = PySequence_Length(plrv); } /* * Traverse the Python lists, in depth-first order, and collect all the * elements at the bottom level into 'elems'/'nulls' arrays. */ elems = palloc(sizeof(Datum) * len); nulls = palloc(sizeof(bool) * len); currelem = 0; PLySequence_ToArray_recurse(arg->u.array.elm, plrv, dims, ndim, 0, elems, nulls, &currelem); for (i = 0; i < ndim; i++) lbs[i] = 1; array = construct_md_array(elems, nulls, ndim, dims, lbs, arg->u.array.elmbasetype, arg->u.array.elm->typlen, arg->u.array.elm->typbyval, arg->u.array.elm->typalign); return PointerGetDatum(array); }
/* * 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); }
Datum alpine_miner_nn_ca_o(PG_FUNCTION_ARGS) { ArrayType *weight_arg, *columns_arg, *input_range_arg, *input_base_arg,*hidden_node_number_arg, *result; Datum *weight_data, *columns_data, *input_range_data, *input_base_data, *hidden_node_number_data, *result_data; bool *weight_nulls, *columns_nulls, *input_range_nulls, *input_base_nulls, *hidden_node_number_nulls,*result_nulls; int weight_count, columns_count, input_range_count, input_base_count, hidden_node_number_count,result_count ; Oid result_eltype; int16 result_typlen; bool result_typbyval; char result_typalign; double output_range_arg,output_base_arg; int hidden_layer_number_arg, output_node_no_arg; bool normalize_arg, numerical_label_arg ; int ndims, *dims, *lbs; int i; int j; int k; int all_hidden_node_count; int weight_index; int hidden_node_number_index = 0; bool null_data; double * input; double * output; int * hidden_node_number; double *weight; double *hidden_node_output; if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3) || PG_ARGISNULL(4) || PG_ARGISNULL(5) || PG_ARGISNULL(6) || PG_ARGISNULL(7) || PG_ARGISNULL(8) || PG_ARGISNULL(9) || PG_ARGISNULL(10)) { PG_RETURN_NULL(); } /* get weight_arg args */ weight_arg = PG_GETARG_ARRAYTYPE_P(0); null_data = alpine_miner_deconstruct_array(weight_arg, &weight_data, &weight_nulls,&weight_count); if (null_data) { PG_RETURN_NULL(); } columns_arg = PG_GETARG_ARRAYTYPE_P(1); null_data = alpine_miner_deconstruct_array(columns_arg, &columns_data, &columns_nulls,&columns_count); if (null_data) { PG_RETURN_NULL(); } /* get input_range_arg args */ input_range_arg = PG_GETARG_ARRAYTYPE_P(2); null_data = alpine_miner_deconstruct_array(input_range_arg, &input_range_data, &input_range_nulls,&input_range_count); if (null_data) { PG_RETURN_NULL(); } /* get input_base_arg args */ input_base_arg = PG_GETARG_ARRAYTYPE_P(3); null_data = alpine_miner_deconstruct_array(input_base_arg, &input_base_data, &input_base_nulls,&input_base_count); if (null_data) { PG_RETURN_NULL(); } /* get hidden_node_number_arg args */ hidden_node_number_arg = PG_GETARG_ARRAYTYPE_P(4); null_data = alpine_miner_deconstruct_array(hidden_node_number_arg, &hidden_node_number_data, &hidden_node_number_nulls,&hidden_node_number_count); if (null_data) { PG_RETURN_NULL(); } hidden_layer_number_arg= PG_GETARG_INT32(5); output_range_arg = PG_GETARG_FLOAT8(6); output_base_arg = PG_GETARG_FLOAT8(7); output_node_no_arg = PG_GETARG_INT32(8); normalize_arg = PG_GETARG_BOOL(9); numerical_label_arg = PG_GETARG_BOOL(10); #ifdef ALPINE_DEBUG elog(WARNING,"%f",DatumGetFloat8(columns_data[0])); #endif input = (double*)palloc(columns_count * sizeof(double));; output = (double*)palloc(output_node_no_arg * sizeof(double)); hidden_node_number = (int*) palloc(hidden_node_number_count * sizeof(int)); weight = (double*)palloc(weight_count * sizeof(double)); for (i = 0; i < weight_count; i++) { weight[i] = DatumGetFloat8(weight_data[i]); } all_hidden_node_count = 0; for (i = 0; i < hidden_layer_number_arg; i++) { hidden_node_number[i] = DatumGetInt32(hidden_node_number_data[i]); all_hidden_node_count += hidden_node_number[i]; } hidden_node_output = (double*)palloc(all_hidden_node_count * sizeof(double)); /* get output array element type */ result_eltype = FLOAT8OID; get_typlenbyvalalign(result_eltype, &result_typlen, &result_typbyval, &result_typalign); /* construct result array */ result_count = output_node_no_arg; result_data = (Datum *)palloc(result_count * sizeof(Datum)); result_nulls = (bool *)palloc(result_count * sizeof(bool)); for (i = 0; i < result_count; i++) { result_nulls[i] = false; } //caculate input if (normalize_arg) { i = 0; while (i < columns_count) { if (DatumGetFloat8(input_range_data[i]) != 0) { input[i] = ((DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i]))/DatumGetFloat8(input_range_data[i])); } else { input[i] = (DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i])); } #ifdef ALPINE_DEBUG elog(WARNING, "input:%f", input[i]); #endif i = i + 1; } } else { i = 0; while (i < columns_count) { input[i] = DatumGetFloat8(columns_data[i]); i = i + 1; } } // caculate hidden node output of 1st layer i = 0; while (i < hidden_node_number[0]) { hidden_node_output[i] = weight[0+i*(columns_count + 1)]; j = 0; while (j < columns_count) { hidden_node_output[i] = hidden_node_output[i]+input[j]*weight[1 + j + i *(columns_count + 1)]; #ifdef ALPINE_DEBUG elog(WARNING,"hiddensum[%d] input[%d] %f weight[%d] %f", i, j,input[j] , 1+j +(i)*(columns_count +1), weight[1+j +i*(columns_count + 1)]); #endif j = j + 1; } if (hidden_node_output[i] < -45.0) { hidden_node_output[i] = 0; } else if (hidden_node_output[i] > 45.0) { hidden_node_output[i] = 1; } else { hidden_node_output[i] = (1.0/(1.0+exp( -1.0 * hidden_node_output[i]))); } #ifdef ALPINE_DEBUG elog(WARNING,"hidden[%d] %f", i, hidden_node_output[i]); #endif i = i + 1; } // calculate hidden layer 2~last output weight_index = hidden_node_number[0] * (columns_count + 1) ; if (hidden_layer_number_arg > 1) { hidden_node_number_index = 0; i = 1; while (i < hidden_layer_number_arg ) { hidden_node_number_index = hidden_node_number_index + hidden_node_number[i - 1]; j = 0; while (j < hidden_node_number[i]) { hidden_node_output[hidden_node_number_index + j] = weight[weight_index + (hidden_node_number[i - 1] +1) * j]; k = 0; while (k < hidden_node_number[i - 1]) { hidden_node_output[hidden_node_number_index + j] = hidden_node_output[hidden_node_number_index + j]+hidden_node_output[hidden_node_number_index - hidden_node_number[i - 1] + k]*weight[weight_index + (hidden_node_number[i - 1] +1) * j + k + 1]; k = k + 1; } if (hidden_node_output[hidden_node_number_index + j] < -45.0) { hidden_node_output[hidden_node_number_index + j] = 0; } else if (hidden_node_output[hidden_node_number_index + j] > 45.0) { hidden_node_output[hidden_node_number_index + j] = 1; } else { hidden_node_output[hidden_node_number_index + j] = (1.0/(1+exp(-1.0*hidden_node_output[hidden_node_number_index+j]))); } j = j + 1; } weight_index = weight_index + hidden_node_number[i] * (hidden_node_number[i - 1] + 1); i = i + 1; } } //compute output value of output node; i = 0; while (i < output_node_no_arg) { output[i] = weight[weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i]; #ifdef ALPINE_DEBUG elog(WARNING,"weightindex:%d,weight[%d] %f",weight_index, weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i, output[i]); #endif j = 0; while (j < hidden_node_number[hidden_layer_number_arg-1]) { #ifdef ALPINE_DEBUG elog(WARNING,"ouput[%d]:%f ,hidden_node_number_index:%d,j:%d, weight[%d]:%f",i,output[i], hidden_node_number_index ,j,1+j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i , weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ]); #endif output[i] = output[i]+hidden_node_output[hidden_node_number_index + j] * weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ]; j = j + 1; } #ifdef ALPINE_DEBUG elog(WARNING,"ouputsum[%d] %f", i, output[i]); #endif if (numerical_label_arg) { output[i] = ((output[i]) * output_range_arg+output_base_arg); #ifdef ALPINE_DEBUG elog(WARNING,"output:%f, %f,%f",output[i],output_range_arg,output_base_arg); #endif } else { if (output[i] < -45.0) { output[i] = 0; } else if (output[i] > 45.0) { output[i] = 1; } else { output[i] = (1.0/(1+exp(-1.0*output[i]))); } } #ifdef ALPINE_DEBUG elog(WARNING,"ouputsum2[%d] %f", i, output[i]); #endif i = i + 1; } ndims = 1; dims = (int *) palloc(sizeof(int)); dims[0] = result_count; lbs = (int *) palloc(sizeof(int)); lbs[0] = 1; for (i = 0; i < output_node_no_arg; i++) { result_data[i] = Float8GetDatum(output[i]); #ifdef ALPINE_DEBUG elog(WARNING,"output[%d]:%f",i, output[i]); #endif } result = construct_md_array((void *)result_data, result_nulls, ndims, dims, lbs, result_eltype, result_typlen, result_typbyval, result_typalign); // pfree(result); pfree(weight_data); pfree(columns_data); pfree(input_range_data); pfree(input_base_data); pfree(hidden_node_number_data); pfree(result_data); pfree(weight_nulls); pfree(columns_nulls); pfree(input_range_nulls); pfree(input_base_nulls); pfree(hidden_node_number_nulls); pfree(result_nulls); pfree(input); pfree(output); pfree(lbs); pfree(dims); pfree(hidden_node_output); pfree(weight); pfree(hidden_node_number); PG_RETURN_ARRAYTYPE_P(result); }