示例#1
0
文件: kv.c 项目: bhaprayan/pipelinedb
/*
 * keyed_min_max_combine_internal
 */
static Datum
keyed_min_max_combine_internal(FunctionCallInfo fcinfo, int sign)
{
	KeyedAggState *kas;
	KeyValue *state;
	KeyValue *incoming = (KeyValue *) PG_GETARG_VARLENA_P(1);
	MemoryContext old;
	MemoryContext context;
	int cmp;
	bool isnull;

	if (!AggCheckCallContext(fcinfo, &context))
		elog(ERROR, "keyed_min_combine_internal called in non-aggregate context");

	if (PG_ARGISNULL(0))
	{
		/*
		 * We can't use the startup function that the aggregate uses because
		 * the combiner Aggref doesn't have all of the original arguments.
		 */
		old = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
		kas = palloc0(sizeof(KeyedAggState));
		kas->key_type = lookup_type_cache(incoming->key_type, TYPECACHE_CMP_PROC_FINFO);
		kas->value_type = lookup_type_cache(incoming->value_type, 0);
		fcinfo->flinfo->fn_extra = kas;
		MemoryContextSwitchTo(old);

		old = MemoryContextSwitchTo(context);
		state = copy_kv(kas, incoming);
		MemoryContextSwitchTo(old);

		PG_RETURN_POINTER(state);
	}

	old = MemoryContextSwitchTo(context);

	state = (KeyValue *) PG_GETARG_VARLENA_P(0);
	kas = (KeyedAggState *) fcinfo->flinfo->fn_extra;
	incoming = point_to_self(kas, (struct varlena *) incoming);

	cmp = sign * compare_keys(kas, state, incoming->key,
			KV_KEY_IS_NULL(incoming), state->key_collation, &isnull);

	if (!isnull && cmp <= 0)
		state = copy_kv(kas, incoming);

	MemoryContextSwitchTo(old);

	PG_RETURN_POINTER(state);
}
示例#2
0
/*
 * Returns whether the Bloom filter contains the item or not
 */
Datum
bloom_contains(PG_FUNCTION_ARGS)
{
	BloomFilter *bloom;
	Datum elem = PG_GETARG_DATUM(1);
	bool contains = false;
	Oid	val_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
	TypeCacheEntry *typ;
	StringInfo buf;

	if (val_type == InvalidOid)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("could not determine input data type")));

	if (PG_ARGISNULL(0))
		PG_RETURN_BOOL(contains);

	bloom = (BloomFilter *) PG_GETARG_VARLENA_P(0);
	typ = lookup_type_cache(val_type, 0);

	buf = makeStringInfo();
	DatumToBytes(elem, typ, buf);

	contains = BloomFilterContains(bloom, buf->data, buf->len);

	pfree(buf->data);
	pfree(buf);

	PG_RETURN_BOOL(contains);
}
示例#3
0
/*
 * worker_hash returns the hashed value of the given value.
 */
Datum
worker_hash(PG_FUNCTION_ARGS)
{
	Datum valueDatum = PG_GETARG_DATUM(0);
	Datum hashedValueDatum = 0;
	TypeCacheEntry *typeEntry = NULL;
	FmgrInfo *hashFunction = NULL;
	Oid valueDataType = InvalidOid;

	/* figure out hash function from the data type */
	valueDataType = get_fn_expr_argtype(fcinfo->flinfo, 0);
	typeEntry = lookup_type_cache(valueDataType, TYPECACHE_HASH_PROC_FINFO);

	if (typeEntry->hash_proc_finfo.fn_oid == InvalidOid)
	{
		ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
						errmsg("cannot find a hash function for the input type"),
						errhint("Cast input to a data type with a hash function.")));
	}

	hashFunction = palloc0(sizeof(FmgrInfo));
	fmgr_info_copy(hashFunction, &(typeEntry->hash_proc_finfo), CurrentMemoryContext);

	/* calculate hash value */
	hashedValueDatum = FunctionCall1(hashFunction, valueDatum);

	PG_RETURN_INT32(hashedValueDatum);
}
示例#4
0
Datum
fss_agg_trans(PG_FUNCTION_ARGS)
{
	MemoryContext old;
	MemoryContext context;
	FSS *state;
	Datum incoming = PG_GETARG_DATUM(1);

	if (!AggCheckCallContext(fcinfo, &context))
		elog(ERROR, "fss_agg_trans called in non-aggregate context");

	old = MemoryContextSwitchTo(context);

	if (PG_ARGISNULL(0))
	{
		uint16_t k = PG_GETARG_INT64(2);
		Oid type = AggGetInitialArgType(fcinfo);
		TypeCacheEntry *typ = lookup_type_cache(type, 0);
		fcinfo->flinfo->fn_extra = typ;
		state = FSSCreate(k, typ);
	}
	else
		state = fss_fix_ptrs(PG_GETARG_VARLENA_P(0));

	FSSIncrement(state, incoming);

	MemoryContextSwitchTo(old);

	PG_RETURN_POINTER(state);
}
示例#5
0
/*
 * cms_topn_frequency is a user-facing UDF which returns the estimated frequency
 * of an item. The first parameter is for CmsTopn and second is for the item to
 * return the frequency.
 */
Datum
cms_topn_frequency(PG_FUNCTION_ARGS)
{
	CmsTopn *cmsTopn = (CmsTopn *) PG_GETARG_VARLENA_P(0);
	ArrayType *topnArray = TopnArray(cmsTopn);
	Datum item = PG_GETARG_DATUM(1);
	Oid itemType = get_fn_expr_argtype(fcinfo->flinfo, 1);
	TypeCacheEntry *itemTypeCacheEntry = NULL;
	Frequency frequency = 0;

	if (itemType == InvalidOid)
	{
		ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
		                errmsg("could not determine input data types")));
	}

	if (topnArray != NULL && itemType != ARR_ELEMTYPE(topnArray))
	{
		ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
		                errmsg("Not proper type for this cms_topn")));
	}

	itemTypeCacheEntry = lookup_type_cache(itemType, 0);
	frequency = CmsTopnEstimateItemFrequency(cmsTopn, item, itemTypeCacheEntry);

	PG_RETURN_INT32(frequency);
}
示例#6
0
/*
 * Returns the estimate normalized frequency of the item
 */
Datum
cmsketch_norm_frequency(PG_FUNCTION_ARGS)
{
	CountMinSketch *cms;
	Datum elem = PG_GETARG_DATUM(1);
	float8 freq = 0;
	Oid	val_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
	TypeCacheEntry *typ;
	StringInfo buf;

	if (val_type == InvalidOid)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("could not determine input data type")));

	if (PG_ARGISNULL(0))
		PG_RETURN_FLOAT8(freq);

	cms = (CountMinSketch *) PG_GETARG_VARLENA_P(0);
	typ = lookup_type_cache(val_type, 0);

	buf = makeStringInfo();
	DatumToBytes(elem, typ, buf);

	freq = CountMinSketchEstimateNormFrequency(cms, buf->data, buf->len);

	pfree(buf->data);
	pfree(buf);

	PG_RETURN_FLOAT8(freq);
}
示例#7
0
 /*
 * minus_oper - identify a suitable minus operator ("-") for a datatype
 *
 * On failure, return NULL if noError, else report a standard error
 */
Operator
minus_oper(Oid argtype, bool noError)
{
	TypeCacheEntry *typentry;
	Oid			oproid;
	Operator	optup;

	/*
	 * Look for a "-" operator for the datatype.  We require it to be an exact
	 * or binary-compatible match, since most callers are not prepared to cope
	 * with adding any run-time type coercion steps.
	 */

	typentry = lookup_type_cache(argtype, TYPECACHE_MINUS_OPR); /*Loads the tuple for this type in the type cache. It also searches and loads the corresponding tuple in the OPERNAMENSP cache*/
	oproid = typentry->minus_opr;/*gets the id of the "-" operator*/

	if (OidIsValid(oproid))
	{	/*We also load the corresponding tuple in the OPEROID cache. This cache allows us to get the operator tuple given its id*/
		optup = SearchSysCache(OPEROID, /*Name of the cache*/
							   ObjectIdGetDatum(oproid), /*Key1*/
							   0, 0, 0);/*We do not use other keys*/
		if (optup == NULL)		/* should not fail */
			elog(ERROR, "cache lookup failed for operator %u", oproid);
		return optup; /*return tuple in OPEROID*/
	}

	if (!noError)
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_FUNCTION),
				 errmsg("could not identify a minus operator for type %s",
						format_type_be(argtype)),
		 errhint("Use an explicit minus operator or modify the query.")));
	return NULL;
}
示例#8
0
/*
 * Returns N-th range (in form of array)
 *
 * First argument is the parent relid.
 * Second argument is the index of the range (if it is negative then the last
 * range will be returned).
 */
Datum
get_range_by_idx(PG_FUNCTION_ARGS)
{
	int parent_oid = DatumGetInt32(PG_GETARG_DATUM(0));
	int idx = DatumGetInt32(PG_GETARG_DATUM(1));
	PartRelationInfo *prel;
	RangeRelation	*rangerel;
	RangeEntry		*ranges;
	RangeEntry		*re;
	Datum			*elems;
	TypeCacheEntry	*tce;

	prel = get_pathman_relation_info(parent_oid, NULL);

	rangerel = get_pathman_range_relation(parent_oid, NULL);

	if (!prel || !rangerel || idx >= (int)rangerel->ranges.length)
		PG_RETURN_NULL();

	tce = lookup_type_cache(prel->atttype, 0);
	ranges = dsm_array_get_pointer(&rangerel->ranges);
	if (idx >= 0)
		re = &ranges[idx];
	else
		re = &ranges[rangerel->ranges.length - 1];

	elems = palloc(2 * sizeof(Datum));
	elems[0] = PATHMAN_GET_DATUM(re->min, rangerel->by_val);
	elems[1] = PATHMAN_GET_DATUM(re->max, rangerel->by_val);

	PG_RETURN_ARRAYTYPE_P(
		construct_array(elems, 2, prel->atttype,
						tce->typlen, tce->typbyval, tce->typalign));
}
示例#9
0
/*
 * Returns the estimate count of the item
 */
Datum
cmsketch_count(PG_FUNCTION_ARGS)
{
	CountMinSketch *cms;
	Datum elem = PG_GETARG_DATUM(1);
	uint32_t count = false;
	Oid	val_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
	TypeCacheEntry *typ;
	Size size;

	if (val_type == InvalidOid)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("could not determine input data type")));

	if (PG_ARGISNULL(0))
		PG_RETURN_INT32(count);

	cms = (CountMinSketch *) PG_GETARG_VARLENA_P(0);
	typ = lookup_type_cache(val_type, 0);
	size = datumGetSize(elem, typ->typbyval, typ->typlen);

	if (typ->typbyval)
		count = CountMinSketchEstimateCount(cms, (char *) &elem, size);
	else
		count = CountMinSketchEstimateCount(cms, DatumGetPointer(elem), size);

	PG_RETURN_INT32(count);
}
示例#10
0
/*
 * reverse_ordering_oper - identify DESC sort operator (">") for a datatype
 *
 * On failure, return NULL if noError, else report a standard error
 */
Operator
reverse_ordering_oper(Oid argtype, bool noError)
{
	TypeCacheEntry *typentry;
	Oid			oproid;
	Operator	optup;

	/*
	 * Look for a ">" operator for the datatype.  We require it to be an exact
	 * or binary-compatible match, since most callers are not prepared to cope
	 * with adding any run-time type coercion steps.
	 *
	 * Note: the search algorithm used by typcache.c ensures that if a ">"
	 * operator is returned, it will be consistent with the "=" operator
	 * returned by equality_oper.  This is critical for sorting and grouping
	 * purposes.
	 */
	typentry = lookup_type_cache(argtype, TYPECACHE_GT_OPR);
	oproid = typentry->gt_opr;

	/*
	 * If the datatype is an array, then we can use array_gt ... but only if
	 * there is a suitable greater-than operator for the element type. (This
	 * check is not in the raw typcache.c code ... should it be?)
	 */
	if (oproid == ARRAY_GT_OP)
	{
		Oid			elem_type = get_element_type(argtype);

		if (OidIsValid(elem_type))
		{
			optup = reverse_ordering_oper(elem_type, true);
			if (optup != NULL)
				ReleaseSysCache(optup);
			else
				oproid = InvalidOid;	/* element type has no ">" */
		}
		else
			oproid = InvalidOid;	/* bogus array type? */
	}

	if (OidIsValid(oproid))
	{
		optup = SearchSysCache(OPEROID,
							   ObjectIdGetDatum(oproid),
							   0, 0, 0);
		if (optup == NULL)		/* should not fail */
			elog(ERROR, "cache lookup failed for operator %u", oproid);
		return optup;
	}

	if (!noError)
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_FUNCTION),
				 errmsg("could not identify an ordering operator for type %s",
						format_type_be(argtype)),
		 errhint("Use an explicit ordering operator or modify the query.")));
	return NULL;
}
示例#11
0
Datum
fss_empty(PG_FUNCTION_ARGS)
{
	Oid typid = PG_GETARG_OID(0);
	uint16_t k = PG_GETARG_INT64(1);
	FSS *fss = FSSCreate(k, lookup_type_cache(typid, 0));
	PG_RETURN_POINTER(fss);
}
示例#12
0
文件: kv.c 项目: bhaprayan/pipelinedb
/*
 * keyed_min_max_finalize
 */
Datum
keyed_min_max_finalize(PG_FUNCTION_ARGS)
{
	KeyValue *kv = (KeyValue *) PG_GETARG_VARLENA_P(0);
	KeyedAggState *kas;

	if (KV_VALUE_IS_NULL(kv))
		PG_RETURN_NULL();

	kas = palloc0(sizeof(KeyedAggState));
	kas->key_type = lookup_type_cache(kv->key_type, TYPECACHE_CMP_PROC_FINFO);
	kas->value_type = lookup_type_cache(kv->value_type, 0);

	kv = point_to_self(kas, (struct varlena *) kv);

	PG_RETURN_POINTER(kv->value);
}
示例#13
0
Datum
cmsketch_add(PG_FUNCTION_ARGS)
{
	CountMinSketch *cms = (CountMinSketch *) PG_GETARG_VARLENA_P(0);
	fcinfo->flinfo->fn_extra = lookup_type_cache(get_fn_expr_argtype(fcinfo->flinfo, 1), 0);
	cms = cmsketch_add_datum(fcinfo, cms, PG_GETARG_DATUM(1));
	PG_RETURN_POINTER(cms);
}
示例#14
0
Datum
fss_emptyp(PG_FUNCTION_ARGS)
{
	Oid typid = PG_GETARG_OID(0);
	uint16_t k = PG_GETARG_INT64(1);
	uint16_t m = PG_GETARG_INT64(2);
	uint16_t h = PG_GETARG_INT64(3);
	FSS *fss = FSSCreateWithMAndH(k, lookup_type_cache(typid, 0), m, h);
	PG_RETURN_POINTER(fss);
}
示例#15
0
/*
 * get_sort_group_operators - get default sorting/grouping operators for type
 *
 * We fetch the "<", "=", and ">" operators all at once to reduce lookup
 * overhead (knowing that most callers will be interested in at least two).
 * However, a given datatype might have only an "=" operator, if it is
 * hashable but not sortable.  (Other combinations of present and missing
 * operators shouldn't happen, unless the system catalogs are messed up.)
 *
 * If an operator is missing and the corresponding needXX flag is true,
 * throw a standard error message, else return InvalidOid.
 *
 * In addition to the operator OIDs themselves, this function can identify
 * whether the "=" operator is hashable.
 *
 * Callers can pass NULL pointers for any results they don't care to get.
 *
 * Note: the results are guaranteed to be exact or binary-compatible matches,
 * since most callers are not prepared to cope with adding any run-time type
 * coercion steps.
 */
void
get_sort_group_operators(Oid argtype,
						 bool needLT, bool needEQ, bool needGT,
						 Oid *ltOpr, Oid *eqOpr, Oid *gtOpr,
						 bool *isHashable)
{
	TypeCacheEntry *typentry;
	int			cache_flags;
	Oid			lt_opr;
	Oid			eq_opr;
	Oid			gt_opr;
	bool		hashable;

	/*
	 * Look up the operators using the type cache.
	 *
	 * Note: the search algorithm used by typcache.c ensures that the results
	 * are consistent, ie all from matching opclasses.
	 */
	if (isHashable != NULL)
		cache_flags = TYPECACHE_LT_OPR | TYPECACHE_EQ_OPR | TYPECACHE_GT_OPR |
			TYPECACHE_HASH_PROC;
	else
		cache_flags = TYPECACHE_LT_OPR | TYPECACHE_EQ_OPR | TYPECACHE_GT_OPR;

	typentry = lookup_type_cache(argtype, cache_flags);
	lt_opr = typentry->lt_opr;
	eq_opr = typentry->eq_opr;
	gt_opr = typentry->gt_opr;
	hashable = OidIsValid(typentry->hash_proc);

	/* Report errors if needed */
	if ((needLT && !OidIsValid(lt_opr)) ||
		(needGT && !OidIsValid(gt_opr)))
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_FUNCTION),
				 errmsg("could not identify an ordering operator for type %s",
						format_type_be(argtype)),
		 errhint("Use an explicit ordering operator or modify the query.")));
	if (needEQ && !OidIsValid(eq_opr))
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_FUNCTION),
				 errmsg("could not identify an equality operator for type %s",
						format_type_be(argtype))));

	/* Return results as needed */
	if (ltOpr)
		*ltOpr = lt_opr;
	if (eqOpr)
		*eqOpr = eq_opr;
	if (gtOpr)
		*gtOpr = gt_opr;
	if (isHashable)
		*isHashable = hashable;
}
示例#16
0
/*
 * cms_topn_add_agg_with_parameters is a aggregate function to add items. It
 * allows to specify parameters of created CmsTopn structure. In addition to
 * cms_topn_add_agg function, it takes error bound and confidence interval
 * parameters as the forth and fifth parameters.
 */
Datum
cms_topn_add_agg_with_parameters(PG_FUNCTION_ARGS)
{
	CmsTopn *currentCmsTopn = NULL;
	CmsTopn *updatedCmsTopn = NULL;
	uint32 topnItemCount = PG_GETARG_UINT32(2);
	float8 errorBound = PG_GETARG_FLOAT8(3);
	float8 confidenceInterval = PG_GETARG_FLOAT8(4);
	Datum newItem = 0;
	TypeCacheEntry *newItemTypeCacheEntry = NULL;
	Oid newItemType = InvalidOid;

	if (!AggCheckCallContext(fcinfo, NULL))
	{
		ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION),
		                errmsg("cms_topn_add_agg_with_parameters called in "
		                       "non-aggregate context")));
	}

	/* check whether cms_topn is null and create if it is */
	if (PG_ARGISNULL(0))
	{
		currentCmsTopn = CreateCmsTopn(topnItemCount, errorBound, confidenceInterval);
	}
	else
	{
		currentCmsTopn = (CmsTopn *) PG_GETARG_VARLENA_P(0);
	}

	/* if new item is null, return current CmsTopn */
	if (PG_ARGISNULL(1))
	{
		PG_RETURN_POINTER(currentCmsTopn);
	}

	/*
	 * Keep type cache entry between subsequent calls in order to get rid of
	 * cache lookup overhead.
	 */
	newItem = PG_GETARG_DATUM(1);
	if (fcinfo->flinfo->fn_extra == NULL)
	{
		newItemType = get_fn_expr_argtype(fcinfo->flinfo, 1);
		newItemTypeCacheEntry = lookup_type_cache(newItemType, 0);
		fcinfo->flinfo->fn_extra = newItemTypeCacheEntry;
	}
	else
	{
		newItemTypeCacheEntry = fcinfo->flinfo->fn_extra;
	}

	updatedCmsTopn = UpdateCmsTopn(currentCmsTopn, newItem, newItemTypeCacheEntry);

	PG_RETURN_POINTER(updatedCmsTopn);
}
示例#17
0
文件: kv.c 项目: bhaprayan/pipelinedb
/*
 * keyed_trans_startup
 *
 * Get type information for the key and value based on argument types
 */
static KeyValue *
keyed_trans_startup(FunctionCallInfo fcinfo)
{
	List *args = NIL;
	KeyedAggState *state;
	Node *node;
	Oid type;
	MemoryContext old;
	KeyValue *result;

	if (AggGetAggref(fcinfo))
		args = AggGetAggref(fcinfo)->args;
	else if (AggGetWindowFunc(fcinfo))
		args = AggGetWindowFunc(fcinfo)->args;
	else
		elog(ERROR, "fcinfo must be an aggregate function call");

	node = linitial(args);
	type = IsA(node, TargetEntry) ? exprType((Node *) ((TargetEntry *) node)->expr) : exprType(node);

	old = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
	state = palloc0(sizeof(KeyedAggState));
	state->key_type = lookup_type_cache(type, TYPECACHE_CMP_PROC_FINFO);

	if (!OidIsValid(state->key_type->cmp_proc))
		elog(ERROR, "could not determine key type");

	node = lsecond(args);
	type = IsA(node, TargetEntry) ? exprType((Node *) ((TargetEntry *) node)->expr) : exprType(node);

	state->value_type = lookup_type_cache(type, 0);
	fcinfo->flinfo->fn_extra = state;
	MemoryContextSwitchTo(old);

	result = set_kv(state, NULL, PG_GETARG_DATUM(1), PG_ARGISNULL(1), PG_GETARG_DATUM(2), PG_ARGISNULL(2));
	result->key_type = state->key_type->type_id;
	result->value_type = state->value_type->type_id;
	result->key_collation = PG_GET_COLLATION();

	return result;
}
示例#18
0
/*
 * enum_cmp_internal is the common engine for all the visible comparison
 * functions, except for enum_eq and enum_ne which can just check for OID
 * equality directly.
 */
static int
enum_cmp_internal(Oid arg1, Oid arg2, FunctionCallInfo fcinfo)
{
	TypeCacheEntry *tcache;

	/*
	 * We don't need the typcache except in the hopefully-uncommon case that
	 * one or both Oids are odd.  This means that cursory testing of code that
	 * fails to pass flinfo to an enum comparison function might not disclose
	 * the oversight.  To make such errors more obvious, Assert that we have a
	 * place to cache even when we take a fast-path exit.
	 */
	Assert(fcinfo->flinfo != NULL);

	/* Equal OIDs are equal no matter what */
	if (arg1 == arg2)
		return 0;

	/* Fast path: even-numbered Oids are known to compare correctly */
	if ((arg1 & 1) == 0 && (arg2 & 1) == 0)
	{
		if (arg1 < arg2)
			return -1;
		else
			return 1;
	}

	/* Locate the typcache entry for the enum type */
	tcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
	if (tcache == NULL)
	{
		HeapTuple	enum_tup;
		Form_pg_enum en;
		Oid			typeoid;

		/* Get the OID of the enum type containing arg1 */
		enum_tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(arg1));
		if (!HeapTupleIsValid(enum_tup))
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
					 errmsg("invalid internal value for enum: %u",
							arg1)));
		en = (Form_pg_enum) GETSTRUCT(enum_tup);
		typeoid = en->enumtypid;
		ReleaseSysCache(enum_tup);
		/* Now locate and remember the typcache entry */
		tcache = lookup_type_cache(typeoid, 0);
		fcinfo->flinfo->fn_extra = (void *) tcache;
	}

	/* The remaining comparison logic is in typcache.c */
	return compare_values_of_enum(tcache, arg1, arg2);
}
示例#19
0
/*
 * equality_oper - identify a suitable equality operator for a datatype
 *
 * On failure, return NULL if noError, else report a standard error
 */
Operator
equality_oper(Oid argtype, bool noError)
{
	TypeCacheEntry *typentry;
	Oid			oproid;
	Operator	optup;

	/*
	 * Look for an "=" operator for the datatype.  We require it to be an
	 * exact or binary-compatible match, since most callers are not prepared
	 * to cope with adding any run-time type coercion steps.
	 */
	typentry = lookup_type_cache(argtype, TYPECACHE_EQ_OPR);
	oproid = typentry->eq_opr;

	/*
	 * If the datatype is an array, then we can use array_eq ... but only if
	 * there is a suitable equality operator for the element type. (This check
	 * is not in the raw typcache.c code ... should it be?)
	 */
	if (oproid == ARRAY_EQ_OP)
	{
		Oid			elem_type = get_element_type(argtype);

		if (OidIsValid(elem_type))
		{
			optup = equality_oper(elem_type, true);
			if (optup != NULL)
				ReleaseSysCache(optup);
			else
				oproid = InvalidOid;	/* element type has no "=" */
		}
		else
			oproid = InvalidOid;	/* bogus array type? */
	}

	if (OidIsValid(oproid))
	{
		optup = SearchSysCache(OPEROID,
							   ObjectIdGetDatum(oproid),
							   0, 0, 0);
		if (optup == NULL)		/* should not fail */
			elog(ERROR, "cache lookup failed for operator %u", oproid);
		return optup;
	}

	if (!noError)
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_FUNCTION),
				 errmsg("could not identify an equality operator for type %s",
						format_type_be(argtype))));
	return NULL;
}
示例#20
0
Datum
bloom_add(PG_FUNCTION_ARGS)
{
	BloomFilter *bloom;

	if (PG_ARGISNULL(0))
		bloom = BloomFilterCreate();
	else
		bloom = (BloomFilter *) PG_GETARG_VARLENA_P(0);

	fcinfo->flinfo->fn_extra = lookup_type_cache(get_fn_expr_argtype(fcinfo->flinfo, 1), 0);
	bloom = bloom_add_datum(fcinfo, bloom, PG_GETARG_DATUM(1));
	PG_RETURN_POINTER(bloom);
}
示例#21
0
static CountMinSketch *
cmsketch_startup(FunctionCallInfo fcinfo, float8 eps, float8 p)
{
	CountMinSketch *cms;
	Oid type = AggGetInitialArgType(fcinfo);

	fcinfo->flinfo->fn_extra = lookup_type_cache(type, 0);

	if (p && eps)
		cms = cmsketch_create(eps, p);
	else
		cms = CountMinSketchCreate();

	return cms;
}
示例#22
0
/*
 * Returns range (min, max) as output parameters
 *
 * first argument is the parent relid
 * second is the partition relid
 * third and forth are MIN and MAX output parameters
 */
Datum
get_partition_range(PG_FUNCTION_ARGS)
{
	int		parent_oid = DatumGetInt32(PG_GETARG_DATUM(0));
	int		child_oid = DatumGetInt32(PG_GETARG_DATUM(1));
	int		nelems = 2;
	int 	i;
	bool	found = false;
	Datum			   *elems;
	PartRelationInfo   *prel;
	RangeRelation	   *rangerel;
	RangeEntry		   *ranges;
	TypeCacheEntry	   *tce;
	ArrayType		   *arr;

	prel = get_pathman_relation_info(parent_oid, NULL);
	
	rangerel = get_pathman_range_relation(parent_oid, NULL);

	if (!prel || !rangerel)
		PG_RETURN_NULL();

	ranges = dsm_array_get_pointer(&rangerel->ranges);
	tce = lookup_type_cache(prel->atttype, 0);

	/* Looking for specified partition */
	for(i=0; i<rangerel->ranges.length; i++)
		if (ranges[i].child_oid == child_oid)
		{
			found = true;
			break;
		}

	if (found)
	{
		bool byVal = rangerel->by_val;

		elems = palloc(nelems * sizeof(Datum));
		elems[0] = PATHMAN_GET_DATUM(ranges[i].min, byVal);
		elems[1] = PATHMAN_GET_DATUM(ranges[i].max, byVal);

		arr = construct_array(elems, nelems, prel->atttype,
							  tce->typlen, tce->typbyval, tce->typalign);
		PG_RETURN_ARRAYTYPE_P(arr);
	}

	PG_RETURN_NULL();
}
示例#23
0
static HyperLogLog *
hll_startup(FunctionCallInfo fcinfo, int p)
{
	HyperLogLog *hll;
	Oid type = AggGetInitialArgType(fcinfo);

	fcinfo->flinfo->fn_extra = lookup_type_cache(type, 0);

	if (p > 0)
		hll = hll_create(p);
	else
		hll = HLLCreate();

	SET_VARSIZE(hll, HLLSize(hll));

	return hll;
}
示例#24
0
static BloomFilter *
bloom_startup(FunctionCallInfo fcinfo, float8 p, uint64_t n)
{
	BloomFilter *bloom;
	Oid type = AggGetInitialArgType(fcinfo);

	fcinfo->flinfo->fn_extra = lookup_type_cache(type, 0);

	if (p && n)
	{
		bloom = bloom_create(p, n);
	}
	else
		bloom = BloomFilterCreate();

	return bloom;
}
示例#25
0
Datum
hll_add(PG_FUNCTION_ARGS)
{
	HyperLogLog *hll = (HyperLogLog *) PG_GETARG_VARLENA_P(0);

	/* Sparse representation can be repalloc'd so create a copy */
	if (HLL_IS_SPARSE(hll))
	{
		HyperLogLog *cpy = palloc(HLLSize(hll));
		memcpy(cpy, hll, HLLSize(hll));
		hll = cpy;
	}

	fcinfo->flinfo->fn_extra = lookup_type_cache(get_fn_expr_argtype(fcinfo->flinfo, 1), 0);
	hll = hll_add_datum(fcinfo, hll, PG_GETARG_DATUM(1));
	PG_RETURN_POINTER(hll);
}
示例#26
0
/*
 * Compare the tuple and slot and check if they have equal values.
 *
 * We use binary datum comparison which might return false negatives but
 * that's the best we can do here as there may be multiple notions of
 * equality for the data types and table columns don't specify which one
 * to use.
 */
static bool
tuple_equals_slot(TupleDesc desc, HeapTuple tup, TupleTableSlot *slot)
{
	Datum		values[MaxTupleAttributeNumber];
	bool		isnull[MaxTupleAttributeNumber];
	int			attrnum;

	heap_deform_tuple(tup, desc, values, isnull);

	/* Check equality of the attributes. */
	for (attrnum = 0; attrnum < desc->natts; attrnum++)
	{
		Form_pg_attribute att;
		TypeCacheEntry *typentry;

		/*
		 * If one value is NULL and other is not, then they are certainly not
		 * equal
		 */
		if (isnull[attrnum] != slot->tts_isnull[attrnum])
			return false;

		/*
		 * If both are NULL, they can be considered equal.
		 */
		if (isnull[attrnum])
			continue;

		att = TupleDescAttr(desc, attrnum);

		typentry = lookup_type_cache(att->atttypid, TYPECACHE_EQ_OPR_FINFO);
		if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_FUNCTION),
					 errmsg("could not identify an equality operator for type %s",
							format_type_be(att->atttypid))));

		if (!DatumGetBool(FunctionCall2(&typentry->eq_opr_finfo,
										values[attrnum],
										slot->tts_values[attrnum])))
			return false;
	}

	return true;
}
示例#27
0
文件: enum.c 项目: Tao-Ma/postgres
/*
 * enum_cmp_internal is the common engine for all the visible comparison
 * functions, except for enum_eq and enum_ne which can just check for OID
 * equality directly.
 */
static int
enum_cmp_internal(Oid arg1, Oid arg2, FunctionCallInfo fcinfo)
{
	TypeCacheEntry *tcache;

	/* Equal OIDs are equal no matter what */
	if (arg1 == arg2)
		return 0;

	/* Fast path: even-numbered Oids are known to compare correctly */
	if ((arg1 & 1) == 0 && (arg2 & 1) == 0)
	{
		if (arg1 < arg2)
			return -1;
		else
			return 1;
	}

	/* Locate the typcache entry for the enum type */
	tcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
	if (tcache == NULL)
	{
		HeapTuple	enum_tup;
		Form_pg_enum en;
		Oid			typeoid;

		/* Get the OID of the enum type containing arg1 */
		enum_tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(arg1));
		if (!HeapTupleIsValid(enum_tup))
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
					 errmsg("invalid internal value for enum: %u",
							arg1)));
		en = (Form_pg_enum) GETSTRUCT(enum_tup);
		typeoid = en->enumtypid;
		ReleaseSysCache(enum_tup);
		/* Now locate and remember the typcache entry */
		tcache = lookup_type_cache(typeoid, 0);
		fcinfo->flinfo->fn_extra = (void *) tcache;
	}

	/* The remaining comparison logic is in typcache.c */
	return compare_values_of_enum(tcache, arg1, arg2);
}
示例#28
0
/*
 * cms_topn_union is a user-facing UDF which takes two cms_topn and returns
 * their union.
 */
Datum
cms_topn_union(PG_FUNCTION_ARGS)
{
	CmsTopn *firstCmsTopn = NULL;
	CmsTopn *secondCmsTopn = NULL;
	CmsTopn *newCmsTopn = NULL;
	ArrayType *firstTopnArray = NULL;
	Size firstTopnArrayLength = 0;
	TypeCacheEntry *itemTypeCacheEntry = NULL;

	/*
	 * If both cms_topn is null, it returns null. If one of the cms_topn's is
	 * null, it returns other cms_topn.
	 */
	if (PG_ARGISNULL(0) && PG_ARGISNULL(1))
	{
		PG_RETURN_NULL();
	}
	else if (PG_ARGISNULL(0))
	{
		secondCmsTopn = (CmsTopn *) PG_GETARG_VARLENA_P(1);
		PG_RETURN_POINTER(secondCmsTopn);
	}
	else if (PG_ARGISNULL(1))
	{
		firstCmsTopn = (CmsTopn *) PG_GETARG_VARLENA_P(0);
		PG_RETURN_POINTER(firstCmsTopn);
	}

	firstCmsTopn = (CmsTopn *) PG_GETARG_VARLENA_P(0);
	secondCmsTopn = (CmsTopn *) PG_GETARG_VARLENA_P(1);
	firstTopnArray = TopnArray(firstCmsTopn);
	firstTopnArrayLength = ARR_DIMS(firstTopnArray)[0];

	if (firstTopnArrayLength != 0)
	{
		Oid itemType = firstTopnArray->elemtype;
		itemTypeCacheEntry = lookup_type_cache(itemType, 0);
	}

	newCmsTopn = CmsTopnUnion(firstCmsTopn, secondCmsTopn, itemTypeCacheEntry);

	PG_RETURN_POINTER(newCmsTopn);
}
示例#29
0
Datum
fss_increment(PG_FUNCTION_ARGS)
{
	FSS *fss;
	TypeCacheEntry *typ = lookup_type_cache(get_fn_expr_argtype(fcinfo->flinfo, 1), 0);

	if (PG_ARGISNULL(0))
		fss = FSSCreate(DEFAULT_K, typ);
	else
	{
		fss = fss_fix_ptrs(PG_GETARG_VARLENA_P(0));

		if (fss->typ.typoid != typ->type_id)
			elog(ERROR, "type mismatch for incoming value");
	}

	FSSIncrement(fss, PG_GETARG_DATUM(1));

	PG_RETURN_POINTER(fss);
}
示例#30
0
Datum
fss_topk(PG_FUNCTION_ARGS)
{
	FSS *fss;
	Datum *datums;
	ArrayType *arr;
	TypeCacheEntry *typ;
	uint16_t found;

	if (PG_ARGISNULL(0))
		PG_RETURN_NULL();

	fss = fss_fix_ptrs(PG_GETARG_VARLENA_P(0));

	datums = FSSTopK(fss, fss->k, &found);
	typ = lookup_type_cache(fss->typ.typoid, 0);
	arr = construct_array(datums, found, typ->type_id, typ->typlen, typ->typbyval, typ->typalign);

	PG_RETURN_ARRAYTYPE_P(arr);
}