/*
 * Trivial picksplit implementaion. Function called only 
 * if user-defined picksplit puts all keys to the one page.
 * That is a bug of user-defined picksplit but we'd like
 * to "fix" that.
 */
static void
genericPickSplit(GISTSTATE *giststate, GistEntryVector *entryvec, GIST_SPLITVEC *v, int attno)
{
	OffsetNumber	 i,
				 	 maxoff;
	int				 nbytes;
	GistEntryVector	*evec;

	maxoff = entryvec->n - 1;

	nbytes = (maxoff + 2) * sizeof(OffsetNumber);

	v->spl_left = (OffsetNumber *) palloc(nbytes);
	v->spl_right = (OffsetNumber *) palloc(nbytes);
	v->spl_nleft = v->spl_nright = 0;

	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
	{
		if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
		{
			v->spl_left[v->spl_nleft] = i;
			v->spl_nleft++;
		}
		else
		{
			v->spl_right[v->spl_nright] = i;
			v->spl_nright++;
		}
	}

	/*
	 * Form unions of each page
	 */

	evec = palloc( sizeof(GISTENTRY) * entryvec->n + GEVHDRSZ );

	evec->n = v->spl_nleft;
	memcpy(evec->vector, entryvec->vector + FirstOffsetNumber, 
						 sizeof(GISTENTRY) * evec->n);
    v->spl_ldatum = FunctionCall2(&giststate->unionFn[attno],
									PointerGetDatum(evec),
									PointerGetDatum(&nbytes));

	evec->n = v->spl_nright;
	memcpy(evec->vector, entryvec->vector + FirstOffsetNumber + v->spl_nleft, 
						 sizeof(GISTENTRY) * evec->n);
    v->spl_rdatum = FunctionCall2(&giststate->unionFn[attno],
									PointerGetDatum(evec),
									PointerGetDatum(&nbytes));
}
/*
 * Inet semi join selectivity estimation for one value
 *
 * The function calculates the probability that there is at least one row
 * in the RHS table that satisfies the "lhs_value op column" condition.
 * It is used in semi join estimation to check a sample from the left hand
 * side table.
 *
 * The MCV and histogram from the right hand side table should be provided as
 * arguments with the lhs_value from the left hand side table for the join.
 * hist_weight is the total number of rows represented by the histogram.
 * For example, if the table has 1000 rows, and 10% of the rows are in the MCV
 * list, and another 10% are NULLs, hist_weight would be 800.
 *
 * First, the lhs_value will be matched to the most common values.  If it
 * matches any of them, 1.0 will be returned, because then there is surely
 * a match.
 *
 * Otherwise, the histogram will be used to estimate the number of rows in
 * the second table that match the condition.  If the estimate is greater
 * than 1.0, 1.0 will be returned, because it means there is a greater chance
 * that the lhs_value will match more than one row in the table.  If it is
 * between 0.0 and 1.0, it will be returned as the probability.
 */
static Selectivity
inet_semi_join_sel(Datum lhs_value,
				   bool mcv_exists, Datum *mcv_values, int mcv_nvalues,
				   bool hist_exists, Datum *hist_values, int hist_nvalues,
				   double hist_weight,
				   FmgrInfo *proc, int opr_codenum)
{
	if (mcv_exists)
	{
		int			i;

		for (i = 0; i < mcv_nvalues; i++)
		{
			if (DatumGetBool(FunctionCall2(proc,
										   lhs_value,
										   mcv_values[i])))
				return 1.0;
		}
	}

	if (hist_exists && hist_weight > 0)
	{
		Selectivity hist_selec;

		/* Commute operator, since we're passing lhs_value on the right */
		hist_selec = inet_hist_value_sel(hist_values, hist_nvalues,
										 lhs_value, -opr_codenum);

		if (hist_selec > 0)
			return Min(1.0, hist_weight * hist_selec);
	}

	return 0.0;
}
Beispiel #3
0
static int
cmpEntries(const void *a, const void *b, void *arg)
{
	const keyEntryData *aa = (const keyEntryData *) a;
	const keyEntryData *bb = (const keyEntryData *) b;
	cmpEntriesArg *data = (cmpEntriesArg *) arg;
	int			res;

	if (aa->isnull)
	{
		if (bb->isnull)
			res = 0;			/* NULL "=" NULL */
		else
			res = 1;			/* NULL ">" not-NULL */
	}
	else if (bb->isnull)
		res = -1;				/* not-NULL "<" NULL */
	else
		res = DatumGetInt32(FunctionCall2(data->cmpDatumFunc,
										  aa->datum, bb->datum));

	/*
	 * Detect if we have any duplicates.  If there are equal keys, qsort
	 * must compare them at some point, else it wouldn't know whether one
	 * should go before or after the other.
	 */
	if (res == 0)
		data->haveDups = true;

	return res;
}
Datum *
extractEntriesS(GinState *ginstate, OffsetNumber attnum, Datum value, int32 *nentries,
				bool *needUnique)
{
	Datum	   *entries;

	entries = (Datum *) DatumGetPointer(FunctionCall2(
									   &ginstate->extractValueFn[attnum - 1],
													  value,
													PointerGetDatum(nentries)
													  ));

	if (entries == NULL)
		*nentries = 0;

	*needUnique = FALSE;
	if (*nentries > 1)
	{
		cmpEntriesData arg;

		arg.cmpDatumFunc = &ginstate->compareFn[attnum - 1];
		arg.needUnique = needUnique;
		qsort_arg(entries, *nentries, sizeof(Datum),
				  (qsort_arg_comparator) cmpEntries, (void *) &arg);
	}

	return entries;
}
Beispiel #5
0
globle int FunctionCall(
  char *name,
  char *args,
  DATA_OBJECT *result)
  {
   FUNCTION_REFERENCE theReference;

   /*=======================================*/
   /* Call the function if it can be found. */
   /*=======================================*/

   if (GetFunctionReference(name,&theReference))
     { return(FunctionCall2(&theReference,args,result)); }

   /*=========================================================*/
   /* Otherwise signal an error if a deffunction, defgeneric, */
   /* or user defined function doesn't exist that matches     */
   /* the specified function name.                            */
   /*=========================================================*/

   PrintErrorID("EVALUATN",2,FALSE);
   PrintRouter(WERROR,"No function, generic function or deffunction of name ");
   PrintRouter(WERROR,name);
   PrintRouter(WERROR," exists for external call.\n");
   return(TRUE);
  }
Beispiel #6
0
/* ----------------
 *		index_getbitmap - get all tuples at once from an index scan
 *
 * Adds the TIDs of all heap tuples satisfying the scan keys to a bitmap.
 * Since there's no interlock between the index scan and the eventual heap
 * access, this is only safe to use with MVCC-based snapshots: the heap
 * item slot could have been replaced by a newer tuple by the time we get
 * to it.
 *
 * Returns the number of matching tuples found.  (Note: this might be only
 * approximate, so it should only be used for statistical purposes.)
 * ----------------
 */
int64
index_getbitmap(IndexScanDesc scan, TIDBitmap *bitmap)
{
	FmgrInfo   *procedure;
	int64		ntids;
	Datum		d;

	SCAN_CHECKS;
	GET_SCAN_PROCEDURE(amgetbitmap);

	/* just make sure this is false... */
	scan->kill_prior_tuple = false;

	/*
	 * have the am's getbitmap proc do all the work.
	 */
	d = FunctionCall2(procedure,
					  PointerGetDatum(scan),
					  PointerGetDatum(bitmap));

	ntids = DatumGetInt64(d);

	/* If int8 is pass-by-ref, must free the result to avoid memory leak */
#ifndef USE_FLOAT8_BYVAL
	pfree(DatumGetPointer(d));
#endif

	pgstat_count_index_tuples(scan->indexRelation, ntids);

	return ntids;
}
Beispiel #7
0
void
hlparsetext(TSCfgInfo * cfg, HLPRSTEXT * prs, QUERYTYPE * query, char *buf, int4 buflen)
{
    int			type,
                lenlemm;
    char	   *lemm = NULL;
    WParserInfo *prsobj = findprs(cfg->prs_id);
    LexizeData	ldata;
    TSLexeme   *norms;
    ParsedLex  *lexs;

    prsobj->prs = (void *) DatumGetPointer(
                      FunctionCall2(
                          &(prsobj->start_info),
                          PointerGetDatum(buf),
                          Int32GetDatum(buflen)
                      )
                  );

    LexizeInit(&ldata, cfg);

    do
    {
        type = DatumGetInt32(FunctionCall3(
                                 &(prsobj->getlexeme_info),
                                 PointerGetDatum(prsobj->prs),
                                 PointerGetDatum(&lemm),
                                 PointerGetDatum(&lenlemm)));

        if (type > 0 && lenlemm >= MAXSTRLEN)
        {
#ifdef IGNORE_LONGLEXEME
            ereport(NOTICE,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("A word you are indexing is too long. It will be ignored.")));
            continue;
#else
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("A word you are indexing is too long")));
#endif
        }

        LexizeAddLemm(&ldata, type, lemm, lenlemm);

        do
        {
            if ((norms = LexizeExec(&ldata, &lexs)) != NULL)
                addHLParsedLex(prs, query, lexs, norms);
            else
                addHLParsedLex(prs, query, lexs, NULL);
        } while (norms);

    } while (type > 0);

    FunctionCall1(
        &(prsobj->end_info),
        PointerGetDatum(prsobj->prs)
    );
}
Beispiel #8
0
/*
 * execTuplesMatch
 *		Return true if two tuples match in all the indicated fields.
 *
 * This actually implements SQL's notion of "not distinct".  Two nulls
 * match, a null and a not-null don't match.
 *
 * slot1, slot2: the tuples to compare (must have same columns!)
 * numCols: the number of attributes to be examined
 * matchColIdx: array of attribute column numbers
 * eqFunctions: array of fmgr lookup info for the equality functions to use
 * evalContext: short-term memory context for executing the functions
 *
 * NB: evalContext is reset each time!
 */
bool
execTuplesMatch(TupleTableSlot *slot1,
				TupleTableSlot *slot2,
				int numCols,
				AttrNumber *matchColIdx,
				FmgrInfo *eqfunctions,
				MemoryContext evalContext)
{
	MemoryContext oldContext;
	bool		result;
	int			i;

	/* Reset and switch into the temp context. */
	MemoryContextReset(evalContext);
	oldContext = MemoryContextSwitchTo(evalContext);

	/*
	 * We cannot report a match without checking all the fields, but we can
	 * report a non-match as soon as we find unequal fields.  So, start
	 * comparing at the last field (least significant sort key). That's the
	 * most likely to be different if we are dealing with sorted input.
	 */
	result = true;

	for (i = numCols; --i >= 0;)
	{
		AttrNumber	att = matchColIdx[i];
		Datum		attr1,
					attr2;
		bool		isNull1,
					isNull2;

		attr1 = slot_getattr(slot1, att, &isNull1);

		attr2 = slot_getattr(slot2, att, &isNull2);

		if (isNull1 != isNull2)
		{
			result = false;		/* one null and one not; they aren't equal */
			break;
		}

		if (isNull1)
			continue;			/* both are null, treat as equal */

		/* Apply the type-specific equality function */

		if (!DatumGetBool(FunctionCall2(&eqfunctions[i],
										attr1, attr2)))
		{
			result = false;		/* they aren't equal */
			break;
		}
	}

	MemoryContextSwitchTo(oldContext);

	return result;
}
Beispiel #9
0
static int
compare_indextuple(const IndexTuple itup1, const IndexTuple itup2,
	ScanKey entry, int keysz, TupleDesc tupdes, bool *hasnull)
{
	int		i;
	int32	compare;

	*hasnull = false;
	for (i = 1; i <= keysz; i++, entry++)
	{
		Datum		attrDatum1,
					attrDatum2;
		bool		isNull1,
					isNull2;

		attrDatum1 = index_getattr(itup1, i, tupdes, &isNull1);
		attrDatum2 = index_getattr(itup2, i, tupdes, &isNull2);
		if (isNull1)
		{
			*hasnull = true;
			if (isNull2)
				compare = 0;		/* NULL "=" NULL */
			else if (entry->sk_flags & SK_BT_NULLS_FIRST)
				compare = -1;		/* NULL "<" NOT_NULL */
			else
				compare = 1;		/* NULL ">" NOT_NULL */
		}
		else if (isNull2)
		{
			*hasnull = true;
			if (entry->sk_flags & SK_BT_NULLS_FIRST)
				compare = 1;		/* NOT_NULL ">" NULL */
			else
				compare = -1;		/* NOT_NULL "<" NULL */
		}
		else
		{
			compare =
#if PG_VERSION_NUM >= 90100
				DatumGetInt32(FunctionCall2Coll(&entry->sk_func,
												entry->sk_collation,
												attrDatum1,
												attrDatum2));
#else
				DatumGetInt32(FunctionCall2(&entry->sk_func,
											attrDatum1,
											attrDatum2));
#endif

			if (entry->sk_flags & SK_BT_DESC)
				compare = -compare;
		}
		if (compare != 0)
			return compare;
	}

	return 0;
}
int
compareEntries(GinState *ginstate, OffsetNumber attnum, Datum a, Datum b)
{
	return DatumGetInt32(
						 FunctionCall2(
									   &ginstate->compareFn[attnum - 1],
									   a, b
									   )
		);
}
Beispiel #11
0
static void
prs_setup_firstcall(FuncCallContext *funcctx, Oid prsid, text *txt)
{
	TupleDesc	tupdesc;
	MemoryContext oldcontext;
	PrsStorage *st;
	TSParserCacheEntry *prs = lookup_ts_parser_cache(prsid);
	char	   *lex = NULL;
	int			llen = 0,
				type = 0;
	void	   *prsdata;

	oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

	st = (PrsStorage *) palloc(sizeof(PrsStorage));
	st->cur = 0;
	st->len = 16;
	st->list = (LexemeEntry *) palloc(sizeof(LexemeEntry) * st->len);

	prsdata = (void *) DatumGetPointer(FunctionCall2(&prs->prsstart,
											   PointerGetDatum(VARDATA(txt)),
									Int32GetDatum(VARSIZE(txt) - VARHDRSZ)));

	while ((type = DatumGetInt32(FunctionCall3(&prs->prstoken,
											   PointerGetDatum(prsdata),
											   PointerGetDatum(&lex),
											   PointerGetDatum(&llen)))) != 0)
	{
		if (st->cur >= st->len)
		{
			st->len = 2 * st->len;
			st->list = (LexemeEntry *) repalloc(st->list, sizeof(LexemeEntry) * st->len);
		}
		st->list[st->cur].lexeme = palloc(llen + 1);
		memcpy(st->list[st->cur].lexeme, lex, llen);
		st->list[st->cur].lexeme[llen] = '\0';
		st->list[st->cur].type = type;
		st->cur++;
	}

	FunctionCall1(&prs->prsend, PointerGetDatum(prsdata));

	st->len = st->cur;
	st->cur = 0;

	funcctx->user_fctx = (void *) st;
	tupdesc = CreateTemplateTupleDesc(2, false);
	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "tokid",
					   INT4OID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "token",
					   TEXTOID, -1, 0);

	funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
	MemoryContextSwitchTo(oldcontext);
}
Beispiel #12
0
void
reestimateParameters(ModelInfo *modelInfo, Node *whereExpr)
{
	//increment the commandCounter so ALL tuples (also the new INSERTED) can be accessed
	CommandCounterIncrement();

	if(sdf==2||sdf==4){
		modelInfo->disAggKeyDenominator = 0;
	}
	FunctionCall2(&(modelInfo->algInfo)->algReestimateUpdate,PointerGetDatum(modelInfo), PointerGetDatum(whereExpr));
}
static int
cmpEntries(const Datum *a, const Datum *b, cmpEntriesData *arg)
{
	int			res = DatumGetInt32(FunctionCall2(arg->cmpDatumFunc,
												  *a, *b));

	if (res == 0)
		*(arg->needUnique) = TRUE;

	return res;
}
Beispiel #14
0
/*
 * Checks if range overlaps with existing partitions.
 * Returns TRUE if overlaps and FALSE otherwise.
 */
Datum
check_overlap(PG_FUNCTION_ARGS)
{
	int parent_oid = DatumGetInt32(PG_GETARG_DATUM(0));
	Datum p1 = PG_GETARG_DATUM(1);
	Oid	  p1_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
	Datum p2 = PG_GETARG_DATUM(2);
	Oid	  p2_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
	PartRelationInfo *prel;
	RangeRelation	 *rangerel;
	RangeEntry		 *ranges;
	FmgrInfo		  cmp_func_1;
	FmgrInfo		  cmp_func_2;
	int i;
	bool byVal;

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

	if (!prel || !rangerel || prel->parttype != PT_RANGE)
		PG_RETURN_NULL();

	/* comparison functions */
	cmp_func_1 = *get_cmp_func(p1_type, prel->atttype);
	cmp_func_2 = *get_cmp_func(p2_type, prel->atttype);

	byVal = rangerel->by_val;
	ranges = (RangeEntry *) dsm_array_get_pointer(&rangerel->ranges);
	for (i=0; i<rangerel->ranges.length; i++)
	{
		int c1 = FunctionCall2(&cmp_func_1, p1,
								PATHMAN_GET_DATUM(ranges[i].max, byVal));
		int c2 = FunctionCall2(&cmp_func_2, p2,
								PATHMAN_GET_DATUM(ranges[i].min, byVal));

		if (c1 < 0 && c2 > 0)
			PG_RETURN_BOOL(true);
	}

	PG_RETURN_BOOL(false);
}
Beispiel #15
0
/*
 * processForecastModel
 *
 * gets called every time an input tuple is processed
 */
void
processForecastModel(ModelInfo *model, Datum value)
{
	// process value internally as double
	double fValue = GetDatumAsDouble(exprType((Node*) model->measure->expr), value);
	
	if((sdf==2||sdf==4)){
		model->disAggKeyDenominator += fValue;
	}
	// call algorithm specific method
	FunctionCall2(&(model->algInfo->algProcessForecast),PointerGetDatum(model->model),Float8GetDatum(fValue));
}
Beispiel #16
0
static OffsetNumber
choose(Relation r, Page p, IndexTuple it, RTSTATE *rtstate)
{
	OffsetNumber maxoff;
	OffsetNumber i;
	Datum		ud,
				id;
	Datum		datum;
	float		usize,
				dsize;
	OffsetNumber which;
	float		which_grow;

	id = IndexTupleGetDatum(it);
	maxoff = PageGetMaxOffsetNumber(p);
	which_grow = -1.0;
	which = -1;

	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
	{
		datum = IndexTupleGetDatum(PageGetItem(p, PageGetItemId(p, i)));
		FunctionCall2(&rtstate->sizeFn, datum,
					  PointerGetDatum(&dsize));
		ud = FunctionCall2(&rtstate->unionFn, datum, id);
		FunctionCall2(&rtstate->sizeFn, ud,
					  PointerGetDatum(&usize));
		pfree(DatumGetPointer(ud));
		if (which_grow < 0 || usize - dsize < which_grow)
		{
			which = i;
			which_grow = usize - dsize;
			if (which_grow == 0)
				break;
		}
	}

	return which;
}
Beispiel #17
0
/*
 * Test whether key1 matches key2. Since the equality functions may leak,
 * reset the temporary context at each call and do all equality calculation
 * in that context.
 */
static int
build_match_key(const void *key1, const void *key2, Size keysize __attribute__((unused)))
{
    Assert(key1);
    Assert(key2);

    BMBuildHashKey *keyData1 = (BMBuildHashKey*)key1;
	Datum *k1 = keyData1->attributeValueArr;
	bool *isNull1 = keyData1->isNullArr;
	
	BMBuildHashKey *keyData2 = (BMBuildHashKey*)key2;
	Datum *k2 = keyData2->attributeValueArr;
	bool *isNull2 = keyData2->isNullArr;
	
    int numKeys = cur_bmbuild->natts;

	int i;
	MemoryContext old;
	int result = 0;

	MemoryContextReset(cur_bmbuild->tmpcxt);
	old = MemoryContextSwitchTo(cur_bmbuild->tmpcxt);

	for(i = 0; i < numKeys; i++)
	{
	    if (isNull1[i] && isNull2[i])
        {
            /* both nulls -- treat as equal so we group them together */
        }
        else if ( isNull1[i] || isNull2[i])
        {
            /* one is null and one non-null -- this is inequal */
            result = 1;
            break;
        }
        else
        {
            /* do the real comparison */
            Datum attr1 = k1[i];
            Datum attr2 = k2[i];
            if (!DatumGetBool(FunctionCall2(&cur_bmbuild->eq_funcs[i], attr1, attr2)))
            {
                result = 1;     /* they aren't equal */
                break;
            }
        }
	}
	MemoryContextSwitchTo(old);
	return result;
}
Beispiel #18
0
/*
 * Compare two keys of the same index column
 */
int
ginCompareEntries(GinState *ginstate, OffsetNumber attnum,
				  Datum a, GinNullCategory categorya,
				  Datum b, GinNullCategory categoryb)
{
	/* if not of same null category, sort by that first */
	if (categorya != categoryb)
		return (categorya < categoryb) ? -1 : 1;

	/* all null items in same category are equal */
	if (categorya != GIN_CAT_NORM_KEY)
		return 0;

	/* both not null, so safe to call the compareFn */
	return DatumGetInt32(FunctionCall2(&ginstate->compareFn[attnum - 1],
									   a, b));
}
Beispiel #19
0
/* ----------------
 *		index_can_return
 *
 *		Does the index access method support index-only scans for the given
 *		column?
 * ----------------
 */
bool
index_can_return(Relation indexRelation, int attno)
{
	FmgrInfo   *procedure;

	RELATION_CHECKS;

	/* amcanreturn is optional; assume FALSE if not provided by AM */
	if (!RegProcedureIsValid(indexRelation->rd_am->amcanreturn))
		return false;

	GET_REL_PROCEDURE(amcanreturn);

	return DatumGetBool(FunctionCall2(procedure,
									  PointerGetDatum(indexRelation),
									  Int32GetDatum(attno)));
}
Beispiel #20
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;
}
Beispiel #21
0
/* ----------------
 *		index_vacuum_cleanup - do post-deletion cleanup of an index
 *
 *		return value is an optional palloc'd struct of statistics
 * ----------------
 */
IndexBulkDeleteResult *
index_vacuum_cleanup(IndexVacuumInfo *info,
					 IndexBulkDeleteResult *stats)
{
	Relation	indexRelation = info->index;
	FmgrInfo	procedure;
	IndexBulkDeleteResult *result;

	RELATION_CHECKS;
	GET_UNCACHED_REL_PROCEDURE(amvacuumcleanup);

	result = (IndexBulkDeleteResult *)
		DatumGetPointer(FunctionCall2(&procedure,
									  PointerGetDatum(info),
									  PointerGetDatum(stats)));

	return result;
}
Beispiel #22
0
/*
 * makes union of two key
 */
void
gistMakeUnionKey(GISTSTATE *giststate, int attno,
				 GISTENTRY *entry1, bool isnull1,
				 GISTENTRY *entry2, bool isnull2,
				 Datum *dst, bool *dstisnull)
{

	int			dstsize;

	static char storage[2 * sizeof(GISTENTRY) + GEVHDRSZ];
	GistEntryVector *evec = (GistEntryVector *) storage;

	evec->n = 2;

	if (isnull1 && isnull2)
	{
		*dstisnull = TRUE;
		*dst = (Datum) 0;
	}
	else
	{
		if (isnull1 == FALSE && isnull2 == FALSE)
		{
			evec->vector[0] = *entry1;
			evec->vector[1] = *entry2;
		}
		else if (isnull1 == FALSE)
		{
			evec->vector[0] = *entry1;
			evec->vector[1] = *entry1;
		}
		else
		{
			evec->vector[0] = *entry2;
			evec->vector[1] = *entry2;
		}

		*dstisnull = FALSE;
		*dst = FunctionCall2(&giststate->unionFn[attno],
							 PointerGetDatum(evec),
							 PointerGetDatum(&dstsize));
	}
}
/*
 * _hash_checkqual -- does the index tuple satisfy the scan conditions?
 */
bool
_hash_checkqual(IndexScanDesc scan, IndexTuple itup)
{
	/*
	 * Currently, we can't check any of the scan conditions since we do not
	 * have the original index entry value to supply to the sk_func. Always
	 * return true; we expect that hashgettuple already set the recheck flag
	 * to make the main indexscan code do it.
	 */
#ifdef NOT_USED
	TupleDesc	tupdesc = RelationGetDescr(scan->indexRelation);
	ScanKey		key = scan->keyData;
	int			scanKeySize = scan->numberOfKeys;

	while (scanKeySize > 0)
	{
		Datum		datum;
		bool		isNull;
		Datum		test;

		datum = index_getattr(itup,
							  key->sk_attno,
							  tupdesc,
							  &isNull);

		/* assume sk_func is strict */
		if (isNull)
			return false;
		if (key->sk_flags & SK_ISNULL)
			return false;

		test = FunctionCall2(&key->sk_func, datum, key->sk_argument);

		if (!DatumGetBool(test))
			return false;

		key++;
		scanKeySize--;
	}
#endif

	return true;
}
Beispiel #24
0
/* ----------------
 * index_getnext_tid - get the next TID from a scan
 *
 * The result is the next TID satisfying the scan keys,
 * or NULL if no more matching tuples exist.
 * ----------------
 */
ItemPointer
index_getnext_tid(IndexScanDesc scan, ScanDirection direction)
{
	FmgrInfo   *procedure;
	bool		found;

	SCAN_CHECKS;
	GET_SCAN_PROCEDURE(amgettuple);

	Assert(TransactionIdIsValid(RecentGlobalXmin));

	/*
	 * The AM's amgettuple proc finds the next index entry matching the scan
	 * keys, and puts the TID into scan->xs_ctup.t_self.  It should also set
	 * scan->xs_recheck and possibly scan->xs_itup, though we pay no attention
	 * to those fields here.
	 */
	found = DatumGetBool(FunctionCall2(procedure,
									   PointerGetDatum(scan),
									   Int32GetDatum(direction)));

	/* Reset kill flag immediately for safety */
	scan->kill_prior_tuple = false;

	/* If we're out of index entries, we're done */
	if (!found)
	{
		/* ... but first, release any held pin on a heap page */
		if (BufferIsValid(scan->xs_cbuf))
		{
			ReleaseBuffer(scan->xs_cbuf);
			scan->xs_cbuf = InvalidBuffer;
		}
		return NULL;
	}

	pgstat_count_index_tuples(scan->indexRelation, 1);

	/* Return the TID of the tuple we found. */
	return &scan->xs_ctup.t_self;
}
Beispiel #25
0
/* ----------------
 *		index_rescan  - (re)start a scan of an index
 *
 * The caller may specify a new set of scankeys (but the number of keys
 * cannot change).	To restart the scan without changing keys, pass NULL
 * for the key array.
 *
 * Note that this is also called when first starting an indexscan;
 * see RelationGetIndexScan.  Keys *must* be passed in that case,
 * unless scan->numberOfKeys is zero.
 * ----------------
 */
void
index_rescan(IndexScanDesc scan, ScanKey key)
{
	FmgrInfo   *procedure;

	SCAN_CHECKS;
	GET_SCAN_PROCEDURE(amrescan);

	/* Release any held pin on a heap page */
	if (BufferIsValid(scan->xs_cbuf))
	{
		ReleaseBuffer(scan->xs_cbuf);
		scan->xs_cbuf = InvalidBuffer;
	}

	scan->kill_prior_tuple = false;		/* for safety */

	FunctionCall2(procedure,
				  PointerGetDatum(scan),
				  PointerGetDatum(key));
}
Beispiel #26
0
/* ----------------
 *		index_getbitmap - get all tuples at once from an index scan
 *
 *		it invokes am's getmulti function to get a bitmap. If am is an on-disk
 *		bitmap index access method (see bitmap.h), then a StreamBitmap is
 *		returned; a TIDBitmap otherwise. Note that an index am's getmulti
 *		function can assume that the bitmap that it's given as argument is of
 *		the same type as what the function constructs itself.
 * ----------------
 */
Node *
index_getbitmap(IndexScanDesc scan, Node *bitmap)
{
	FmgrInfo   *procedure;
	Node		*bm;

	SCAN_CHECKS;
	GET_SCAN_PROCEDURE(amgetbitmap);

	/* just make sure this is false... */
	scan->kill_prior_tuple = false;

	/*
	 * have the am's getbitmap proc do all the work.
	 */
	bm = (Node *) DatumGetPointer(FunctionCall2(procedure,
									  PointerGetDatum(scan),
									  PointerGetDatum(bitmap)));

	return bm;
}
Beispiel #27
0
/* ----------------
 *		index_getnext_indexitem - get the next index tuple from a scan
 *
 * Finds the next index tuple satisfying the scan keys.  Note that the
 * corresponding heap tuple is not accessed, and thus no time qual (snapshot)
 * check is done, other than the index AM's internal check for killed tuples
 * (which most callers of this routine will probably want to suppress by
 * setting scan->ignore_killed_tuples = false).
 *
 * On success (TRUE return), the found index TID is in scan->currentItemData,
 * and its heap TID is in scan->xs_ctup.t_self.  scan->xs_cbuf is untouched.
 * ----------------
 */
bool
index_getnext_indexitem(IndexScanDesc scan,
						ScanDirection direction)
{
	bool		found;

	SCAN_CHECKS;

	/* just make sure this is false... */
	scan->kill_prior_tuple = false;

	/*
	 * have the am's gettuple proc do all the work. index_beginscan
	 * already set up fn_getnext.
	 */
	found = DatumGetBool(FunctionCall2(&scan->fn_getnext,
									   PointerGetDatum(scan),
									   Int32GetDatum(direction)));

	return found;
}
/*
 * Inet MCV vs MCV join selectivity estimation
 *
 * We simply add up the fractions of the populations that satisfy the clause.
 * The result is exact and does not need to be scaled further.
 */
static Selectivity
inet_mcv_join_sel(Datum *mcv1_values, float4 *mcv1_numbers, int mcv1_nvalues,
				  Datum *mcv2_values, float4 *mcv2_numbers, int mcv2_nvalues,
				  Oid operator)
{
	Selectivity selec = 0.0;
	FmgrInfo	proc;
	int			i,
				j;

	fmgr_info(get_opcode(operator), &proc);

	for (i = 0; i < mcv1_nvalues; i++)
	{
		for (j = 0; j < mcv2_nvalues; j++)
			if (DatumGetBool(FunctionCall2(&proc,
										   mcv1_values[i],
										   mcv2_values[j])))
				selec += mcv1_numbers[i] * mcv2_numbers[j];
	}
	return selec;
}
Beispiel #29
0
/*
 * _hash_checkqual -- does the index tuple satisfy the scan conditions?
 */
bool
_hash_checkqual(IndexScanDesc scan, IndexTuple itup)
{
	TupleDesc	tupdesc = RelationGetDescr(scan->indexRelation);
	ScanKey		key = scan->keyData;
	int			scanKeySize = scan->numberOfKeys;

	IncrIndexProcessed();

	while (scanKeySize > 0)
	{
		Datum		datum;
		bool		isNull;
		Datum		test;

		datum = index_getattr(itup,
							  key->sk_attno,
							  tupdesc,
							  &isNull);

		/* assume sk_func is strict */
		if (isNull)
			return false;
		if (key->sk_flags & SK_ISNULL)
			return false;

		test = FunctionCall2(&key->sk_func, datum, key->sk_argument);

		if (!DatumGetBool(test))
			return false;

		key++;
		scanKeySize--;
	}

	return true;
}
Beispiel #30
0
/* ----------------
 *		index_getnext_indexitem - get the next index tuple from a scan
 *
 * Finds the next index tuple satisfying the scan keys.  Note that the
 * corresponding heap tuple is not accessed, and thus no time qual (snapshot)
 * check is done, other than the index AM's internal check for killed tuples
 * (which most callers of this routine will probably want to suppress by
 * setting scan->ignore_killed_tuples = false).
 *
 * On success (TRUE return), the heap TID of the found index entry is in
 * scan->xs_ctup.t_self.  scan->xs_cbuf is untouched.
 * ----------------
 */
bool
index_getnext_indexitem(IndexScanDesc scan,
						ScanDirection direction)
{
	FmgrInfo   *procedure;
	bool		found;

	SCAN_CHECKS;
	GET_SCAN_PROCEDURE(amgettuple);

	/* just make sure this is false... */
	scan->kill_prior_tuple = false;

	/*
	 * have the am's gettuple proc do all the work.
	 */
	found = DatumGetBool(FunctionCall2(procedure,
									   PointerGetDatum(scan),
									   Int32GetDatum(direction)));

	pgstat_count_index_tuples(scan->indexRelation, 1 /*ntids*/);

	return found;
}