/* check whether the content in the given bytea is safe for mfvtransval */ void check_mfvtransval(bytea *storage) { size_t left_len = VARSIZE(storage); size_t cur_size = 0; size_t cur_capacity = 0; Oid outFuncOid; bool typIsVarLen; mfvtransval *mfv = NULL; if (left_len < VARHDRSZ + sizeof(mfvtransval)) { elog(ERROR, "invalid transition state for mfvsketch"); } mfv = (mfvtransval*)VARDATA(storage); left_len -= VARHDRSZ + sizeof(mfvtransval); if (mfv->next_mfv > mfv->max_mfvs) { elog(ERROR, "invalid transition state for mfvsketch"); } if (mfv->next_offset + VARHDRSZ > VARSIZE(storage)) { elog(ERROR, "invalid transition state for mfvsketch"); } if (InvalidOid == mfv->typOid) { elog(ERROR, "invalid transition state for mfvsketch"); } getTypeOutputInfo(mfv->typOid, &outFuncOid, &typIsVarLen); if (mfv->outFuncOid != outFuncOid || mfv->typLen != get_typlen(mfv->typOid) || mfv->typByVal != get_typbyval(mfv->typOid)) { elog(ERROR, "invalid transition state for mfvsketch"); } if (left_len < sizeof(offsetcnt)*mfv->max_mfvs) { elog(ERROR, "invalid transition state for mfvsketch"); } /* offset is relative to mfvtransval */ left_len = VARSIZE(storage) - VARHDRSZ; /* * the following checking may be inefficiency, but by doing this centrally, * we can avoid spreading the checking code everywhere. */ for (unsigned i = 0; i < mfv->next_mfv; i ++) { cur_capacity = left_len - mfv->mfvs[i].offset; if (mfv->mfvs[i].offset > left_len) { elog(ERROR, "invalid transition state for mfvsketch"); } cur_size = ExtractDatumLen(PointerGetDatum(MFV_DATA(mfv) + mfv->mfvs[i].offset), mfv->typLen, mfv->typByVal, cur_capacity); if (cur_size > cur_capacity) { elog(ERROR, "invalid transition state for mfvsketch"); } } }
/* * free_attstatsslot * Free data allocated by get_attstatsslot * * atttype need be valid only if values != NULL. */ void free_attstatsslot(Oid atttype, Datum *values, int nvalues, float4 *numbers, int nnumbers) { if (values) { if (!get_typbyval(atttype)) { int i; for (i = 0; i < nvalues; i++) pfree(DatumGetPointer(values[i])); } pfree(values); } if (numbers) pfree(numbers); }
/* check whether the content in the given bytea is safe for mfvtransval */ void check_mfvtransval(bytea *storage) { size_t left_len = VARSIZE(storage); Oid outFuncOid; bool typIsVarLen; mfvtransval *mfv = NULL; if (left_len < VARHDRSZ + sizeof(mfvtransval)) { elog(ERROR, "invalid transition state for mfvsketch"); } mfv = (mfvtransval*)VARDATA(storage); left_len -= VARHDRSZ + sizeof(mfvtransval); if (mfv->next_mfv > mfv->max_mfvs) { elog(ERROR, "invalid transition state for mfvsketch"); } if (mfv->next_offset + VARHDRSZ > VARSIZE(storage)) { elog(ERROR, "invalid transition state for mfvsketch"); } if (InvalidOid == mfv->typOid) { elog(ERROR, "invalid transition state for mfvsketch"); } getTypeOutputInfo(mfv->typOid, &outFuncOid, &typIsVarLen); if (mfv->outFuncOid != outFuncOid || mfv->typLen != get_typlen(mfv->typOid) || mfv->typByVal != get_typbyval(mfv->typOid)) { elog(ERROR, "invalid transition state for mfvsketch"); } if (left_len < sizeof(offsetcnt)*mfv->max_mfvs) { elog(ERROR, "invalid transition state for mfvsketch"); } }
/*! * Initialize an mfv sketch * \param max_mfvs the number of "bins" in the histogram * \param typOid the type ID for the column */ bytea *mfv_init_transval(int max_mfvs, Oid typOid) { int initial_size; bool typIsVarLen; bytea * transblob; mfvtransval *transval; /* * initialize mfvtransval, using palloc0 to zero it out. * if typlen is positive (fixed), size chosen accurately. * Else we'll do a conservative estimate of 16 bytes, and repalloc as needed. */ if ((initial_size = get_typlen(typOid)) > 0) initial_size *= max_mfvs*get_typlen(typOid); else /* guess */ initial_size = max_mfvs*16; transblob = (bytea *)palloc0(MFV_TRANSVAL_SZ(max_mfvs) + initial_size); SET_VARSIZE(transblob, MFV_TRANSVAL_SZ(max_mfvs) + initial_size); transval = (mfvtransval *)VARDATA(transblob); transval->max_mfvs = max_mfvs; transval->next_mfv = 0; transval->next_offset = MFV_TRANSVAL_SZ(max_mfvs)-VARHDRSZ; transval->typOid = typOid; getTypeOutputInfo(transval->typOid, &(transval->outFuncOid), &(typIsVarLen)); transval->typLen = get_typlen(transval->typOid); transval->typByVal = get_typbyval(transval->typOid); if (!transval->outFuncOid) { /* no outFunc for this type! */ elog(ERROR, "no outFunc for type %d", transval->typOid); } return(transblob); }