diff --git a/src/backend/utils/adt/array_typanalyze.c b/src/backend/utils/adt/array_typanalyze.c
new file mode 100644
index ffe8035..bd3f2cb
*** a/src/backend/utils/adt/array_typanalyze.c
--- b/src/backend/utils/adt/array_typanalyze.c
*************** compute_array_stats(VacAttrStats *stats,
*** 510,517 ****
  		else
  			num_mcelem = track_len;
  
  		/* Generate MCELEM slot entry */
! 		if (num_mcelem > 0)
  		{
  			MemoryContext old_context;
  			Datum	   *mcelem_values;
--- 510,526 ----
  		else
  			num_mcelem = track_len;
  
+ 		/*
+ 		 * If we didn't accumulate any frequent enough elements then use
+ 		 * cutoff_freq as minfreq. Idea is that we assume all frequiencies to
+ 		 * be in interval [0; cutoff_freq). Thus cutoff_freq / 2 would be sane
+ 		 * estimate for element frequency.
+ 		 */
+ 		if (num_mcelem == 0)
+ 			minfreq = cutoff_freq;
+ 
  		/* Generate MCELEM slot entry */
! 		if (num_mcelem >= 0)
  		{
  			MemoryContext old_context;
  			Datum	   *mcelem_values;
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
new file mode 100644
index 093da76..f9a5b71
*** a/src/backend/utils/cache/lsyscache.c
--- b/src/backend/utils/cache/lsyscache.c
*************** get_attstatsslot(HeapTuple statstuple,
*** 2863,2914 ****
  							  Anum_pg_statistic_stavalues1 + i,
  							  &isnull);
  		if (isnull)
! 			elog(ERROR, "stavalues is null");
! 		statarray = DatumGetArrayTypeP(val);
  
! 		/*
! 		 * Need to get info about the array element type.  We look at the
! 		 * actual element type embedded in the array, which might be only
! 		 * binary-compatible with the passed-in atttype.  The info we extract
! 		 * here should be the same either way, but deconstruct_array is picky
! 		 * about having an exact type OID match.
! 		 */
! 		arrayelemtype = ARR_ELEMTYPE(statarray);
! 		typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrayelemtype));
! 		if (!HeapTupleIsValid(typeTuple))
! 			elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
! 		typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
  
! 		/* Deconstruct array into Datum elements; NULLs not expected */
! 		deconstruct_array(statarray,
! 						  arrayelemtype,
! 						  typeForm->typlen,
! 						  typeForm->typbyval,
! 						  typeForm->typalign,
! 						  values, NULL, nvalues);
  
! 		/*
! 		 * If the element type is pass-by-reference, we now have a bunch of
! 		 * Datums that are pointers into the syscache value.  Copy them to
! 		 * avoid problems if syscache decides to drop the entry.
! 		 */
! 		if (!typeForm->typbyval)
! 		{
! 			for (j = 0; j < *nvalues; j++)
  			{
! 				(*values)[j] = datumCopy((*values)[j],
! 										 typeForm->typbyval,
! 										 typeForm->typlen);
  			}
- 		}
  
! 		ReleaseSysCache(typeTuple);
  
! 		/*
! 		 * Free statarray if it's a detoasted copy.
! 		 */
! 		if ((Pointer) statarray != DatumGetPointer(val))
! 			pfree(statarray);
  	}
  
  	if (numbers)
--- 2863,2921 ----
  							  Anum_pg_statistic_stavalues1 + i,
  							  &isnull);
  		if (isnull)
! 		{
! 			*values = NULL;
! 			*nvalues = 0;
! 		}
! 		else
! 		{
! 			statarray = DatumGetArrayTypeP(val);
  
! 			/*
! 			 * Need to get info about the array element type.  We look at the
! 			 * actual element type embedded in the array, which might be only
! 			 * binary-compatible with the passed-in atttype.  The info we
! 			 * extract here should be the same either way, but deconstruct_array
! 			 * is picky about having an exact type OID match.
! 			 */
! 			arrayelemtype = ARR_ELEMTYPE(statarray);
! 			typeTuple = SearchSysCache1(TYPEOID,
! 											ObjectIdGetDatum(arrayelemtype));
! 			if (!HeapTupleIsValid(typeTuple))
! 				elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
! 			typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
  
! 			/* Deconstruct array into Datum elements; NULLs not expected */
! 			deconstruct_array(statarray,
! 							  arrayelemtype,
! 							  typeForm->typlen,
! 							  typeForm->typbyval,
! 							  typeForm->typalign,
! 							  values, NULL, nvalues);
  
! 			/*
! 			 * If the element type is pass-by-reference, we now have a bunch of
! 			 * Datums that are pointers into the syscache value.  Copy them to
! 			 * avoid problems if syscache decides to drop the entry.
! 			 */
! 			if (!typeForm->typbyval)
  			{
! 				for (j = 0; j < *nvalues; j++)
! 				{
! 					(*values)[j] = datumCopy((*values)[j],
! 											 typeForm->typbyval,
! 											 typeForm->typlen);
! 				}
  			}
  
! 			ReleaseSysCache(typeTuple);
  
! 			/*
! 			 * Free statarray if it's a detoasted copy.
! 			 */
! 			if ((Pointer) statarray != DatumGetPointer(val))
! 				pfree(statarray);
! 		}
  	}
  
  	if (numbers)
*************** get_attstatsslot(HeapTuple statstuple,
*** 2917,2944 ****
  							  Anum_pg_statistic_stanumbers1 + i,
  							  &isnull);
  		if (isnull)
! 			elog(ERROR, "stanumbers is null");
! 		statarray = DatumGetArrayTypeP(val);
  
! 		/*
! 		 * We expect the array to be a 1-D float4 array; verify that. We don't
! 		 * need to use deconstruct_array() since the array data is just going
! 		 * to look like a C array of float4 values.
! 		 */
! 		narrayelem = ARR_DIMS(statarray)[0];
! 		if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
! 			ARR_HASNULL(statarray) ||
! 			ARR_ELEMTYPE(statarray) != FLOAT4OID)
! 			elog(ERROR, "stanumbers is not a 1-D float4 array");
! 		*numbers = (float4 *) palloc(narrayelem * sizeof(float4));
! 		memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
! 		*nnumbers = narrayelem;
  
! 		/*
! 		 * Free statarray if it's a detoasted copy.
! 		 */
! 		if ((Pointer) statarray != DatumGetPointer(val))
! 			pfree(statarray);
  	}
  
  	return true;
--- 2924,2958 ----
  							  Anum_pg_statistic_stanumbers1 + i,
  							  &isnull);
  		if (isnull)
! 		{
! 			*numbers = NULL;
! 			*nnumbers = 0;
! 		}
! 		else
! 		{
! 			statarray = DatumGetArrayTypeP(val);
  
! 			/*
! 			 * We expect the array to be a 1-D float4 array; verify that. We
! 			 * don't need to use deconstruct_array() since the array data is
! 			 * just going to look like a C array of float4 values.
! 			 */
! 			narrayelem = ARR_DIMS(statarray)[0];
! 			if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
! 				ARR_HASNULL(statarray) ||
! 				ARR_ELEMTYPE(statarray) != FLOAT4OID)
! 				elog(ERROR, "stanumbers is not a 1-D float4 array");
! 			*numbers = (float4 *) palloc(narrayelem * sizeof(float4));
! 			memcpy(*numbers, ARR_DATA_PTR(statarray),
! 												narrayelem * sizeof(float4));
! 			*nnumbers = narrayelem;
  
! 			/*
! 			 * Free statarray if it's a detoasted copy.
! 			 */
! 			if ((Pointer) statarray != DatumGetPointer(val))
! 				pfree(statarray);
! 		}
  	}
  
  	return true;
