/* * 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); }
/* * 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); }
/* * 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); }
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); }
/* * 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); }
/* * 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); }
/* * 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; }
/* * 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)); }
/* * 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); }
/* * 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; }
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); }
/* * 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); }
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); }
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); }
/* * 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; }
/* * 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); }
/* * 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; }
/* * 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); }
/* * 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; }
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); }
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; }
/* * 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(); }
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; }
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; }
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); }
/* * 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; }
/* * 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); }
/* * 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); }
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); }
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); }