Beispiel #1
0
static bool
assert_equals_base(FunctionCallInfo fcinfo)
{
	Datum 		value1 = PG_GETARG_DATUM(0);
	Datum		value2 = PG_GETARG_DATUM(1);
	Oid		*ptr;

	ptr = (Oid *) fcinfo->flinfo->fn_extra;
	if (ptr == NULL)
	{
		Oid	  valtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
		Oid eqopfcid;

		if (!OidIsValid(valtype))
	    		elog(ERROR, "could not determine data type of input");

		eqopfcid = equality_oper_funcid(valtype);

		if (!OidIsValid(eqopfcid))
			ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				errmsg("unknown equal operand for datatype")));

    		/* First time calling for current query: allocate storage */
        	fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
            						                    sizeof(Oid));
                ptr = (Oid *) fcinfo->flinfo->fn_extra;
                *ptr = eqopfcid;
        }

	return DatumGetBool(OidFunctionCall2(*ptr, value1, value2));
}
/*
 * init_scankeys
 *
 * Initialize the scan keys.
 */
static void
init_scankeys(TupleDesc tupleDesc,
			  int nkeys, ScanKey scanKeys,
			  StrategyNumber *strategyNumbers)
{
	int keyNo;

	Assert(nkeys <= tupleDesc->natts);
	
	for (keyNo = 0; keyNo < nkeys; keyNo ++)
	{
		ScanKey scanKey = (ScanKey)(((char *)scanKeys) + 
									keyNo * sizeof(ScanKeyData));
		RegProcedure opfuncid;
		StrategyNumber strategyNumber = strategyNumbers[keyNo];

		Assert(strategyNumber <= BTMaxStrategyNumber &&
			   strategyNumber != InvalidStrategy);
		
		if (strategyNumber == BTEqualStrategyNumber)
		{
			opfuncid = equality_oper_funcid(tupleDesc->attrs[keyNo]->atttypid);
			ScanKeyEntryInitialize(scanKey,
								   0, /* sk_flag */
								   keyNo + 1, /* attribute number to scan */
								   BTEqualStrategyNumber, /* strategy */
								   InvalidOid, /* strategy subtype */
								   opfuncid, /* reg proc to use */
								   0 /* constant */
				);
		}
		else
		{
			Oid gtOid, leOid;
			
			gtOid = reverse_ordering_oper_opid(tupleDesc->attrs[keyNo]->atttypid);
			leOid = get_negator(gtOid);
			opfuncid = get_opcode(leOid);
			
			ScanKeyEntryInitialize(scanKey,
								   0, /* sk_flag */
								   keyNo + 1, /* attribute number to scan */
								   strategyNumber, /* strategy */
								   InvalidOid, /* strategy subtype */
								   opfuncid, /* reg proc to use */
								   0 /* constant */
				);
		}
	}
}
Beispiel #3
0
/*
 * execTuplesMatchPrepare
 *		Look up the equality functions needed for execTuplesMatch or
 *		execTuplesUnequal.
 *
 * The result is a palloc'd array.
 */
FmgrInfo *
execTuplesMatchPrepare(TupleDesc tupdesc,
					   int numCols,
					   AttrNumber *matchColIdx)
{
	FmgrInfo   *eqfunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo));
	int			i;

	for (i = 0; i < numCols; i++)
	{
		AttrNumber	att = matchColIdx[i];
		Oid			typid = tupdesc->attrs[att - 1]->atttypid;
		Oid			eq_function;

		eq_function = equality_oper_funcid(typid);/*GIVEN A TYPE GET THE EQUALITY FUNCTION*/
		fmgr_info(eq_function, &eqfunctions[i]);
	}

	return eqfunctions;
}
Beispiel #4
0
/*
 * decode(lhs, [rhs, ret], ..., [default])
 */
Datum
ora_decode(PG_FUNCTION_ARGS)
{
	int		nargs;
	int		i;
	int		retarg;

	/* default value is last arg or NULL. */
	nargs = PG_NARGS();
	if (nargs % 2 == 0)
	{
		retarg = nargs - 1;
		nargs -= 1;		/* ignore the last argument */
	}
	else
		retarg = -1;	/* NULL */

	if (PG_ARGISNULL(0))
	{
		for (i = 1; i < nargs; i += 2)
		{
			if (PG_ARGISNULL(i))
			{
				retarg = i + 1;
				break;
			}
		}
	}
	else
	{
		FmgrInfo   *eq;
#if PG_VERSION_NUM >= 90100
		Oid		collation = PG_GET_COLLATION();
#endif

		/*
		 * On first call, get the input type's operator '=' and save at
		 * fn_extra.
		 */
		if (fcinfo->flinfo->fn_extra == NULL)
		{
			MemoryContext	oldctx;
			Oid				typid = get_fn_expr_argtype(fcinfo->flinfo, 0);
			Oid				eqoid = equality_oper_funcid(typid);

			oldctx = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
			eq = palloc(sizeof(FmgrInfo));
			fmgr_info(eqoid, eq);
			MemoryContextSwitchTo(oldctx);

			fcinfo->flinfo->fn_extra = eq;
		}
		else
			eq = fcinfo->flinfo->fn_extra;

		for (i = 1; i < nargs; i += 2)
		{
			FunctionCallInfoData	func;
			Datum					result;

			if (PG_ARGISNULL(i))
				continue;

#if PG_VERSION_NUM >= 90100
			InitFunctionCallInfoData(func, eq, 2, collation, NULL, NULL);
#else
			InitFunctionCallInfoData(func, eq, 2, NULL, NULL);
#endif
			func.arg[0] = PG_GETARG_DATUM(0);
			func.arg[1] = PG_GETARG_DATUM(i);
			func.argnull[0] = false;
			func.argnull[1] = false;
			result = FunctionCallInvoke(&func);

			if (!func.isnull && DatumGetBool(result))
			{
				retarg = i + 1;
				break;
			}
		}
	}

	if (retarg < 0 || PG_ARGISNULL(retarg))
		PG_RETURN_NULL();
	else
		PG_RETURN_DATUM(PG_GETARG_DATUM(retarg));
}
Beispiel #5
0
/*
 * _bitmap_init_buildstate() -- initialize the build state before building
 *	a bitmap index.
 */
void
_bitmap_init_buildstate(Relation index, BMBuildState *bmstate)
{
	MIRROREDLOCK_BUFMGR_DECLARE;

	BMMetaPage	mp;
	HASHCTL		hash_ctl;
	int			hash_flags;
	int			i;
	Buffer		metabuf;


	/* initialize the build state */
	bmstate->bm_tupDesc = RelationGetDescr(index);
	bmstate->bm_tidLocsBuffer = (BMTidBuildBuf *)
		palloc(sizeof(BMTidBuildBuf));
	bmstate->bm_tidLocsBuffer->byte_size = 0;
	bmstate->bm_tidLocsBuffer->lov_blocks = NIL;
	bmstate->bm_tidLocsBuffer->max_lov_block = InvalidBlockNumber;
	
	// -------- MirroredLock ----------
	MIRROREDLOCK_BUFMGR_LOCK;
	
	metabuf = _bitmap_getbuf(index, BM_METAPAGE, BM_READ);
	mp = _bitmap_get_metapage_data(index, metabuf);
	_bitmap_open_lov_heapandindex(index, mp, &(bmstate->bm_lov_heap),
								  &(bmstate->bm_lov_index), 
								  RowExclusiveLock);

	_bitmap_relbuf(metabuf);
	
	MIRROREDLOCK_BUFMGR_UNLOCK;
	// -------- MirroredLock ----------
	
	cur_bmbuild = (BMBuildHashData *)palloc(sizeof(BMBuildHashData));
	cur_bmbuild->hash_funcs = (FmgrInfo *)
						palloc(sizeof(FmgrInfo) * bmstate->bm_tupDesc->natts);
	cur_bmbuild->eq_funcs = (FmgrInfo *)
                        palloc(sizeof(FmgrInfo) * bmstate->bm_tupDesc->natts);
    cur_bmbuild->hash_func_is_strict = (bool *)
                        palloc(sizeof(bool) * bmstate->bm_tupDesc->natts);

	for (i = 0; i < bmstate->bm_tupDesc->natts; i++)
	{
		Oid			typid = bmstate->bm_tupDesc->attrs[i]->atttypid;
		Operator	optup;
		Oid			eq_opr;
		Oid			eq_function;
		Oid			left_hash_function;
		Oid			right_hash_function;

		optup = equality_oper(typid, false);
		eq_opr = oprid(optup);
		eq_function = oprfuncid(optup);
		ReleaseOperator(optup);

		if (!get_op_hash_functions(eq_opr,
								   &left_hash_function,
								   &right_hash_function))
		{
			pfree(cur_bmbuild);
			cur_bmbuild = NULL;
			break;
		}

		Assert(left_hash_function == right_hash_function);
		fmgr_info(eq_function, &cur_bmbuild->eq_funcs[i]);
		fmgr_info(right_hash_function, &cur_bmbuild->hash_funcs[i]);
        cur_bmbuild->hash_func_is_strict[i] = func_strict(right_hash_function);
	}

	if (cur_bmbuild)
	{
		cur_bmbuild->natts = bmstate->bm_tupDesc->natts;
		cur_bmbuild->tmpcxt = AllocSetContextCreate(CurrentMemoryContext,
        	                      "Bitmap build temp space",
            	                  ALLOCSET_DEFAULT_MINSIZE,
                	              ALLOCSET_DEFAULT_INITSIZE,
                    	          ALLOCSET_DEFAULT_MAXSIZE);

		/* setup the hash table */
	    MemSet(&hash_ctl, 0, sizeof(hash_ctl));

	    /**
	     * Reserve enough space for the hash key header and then the data segments (values followed by nulls)
	     */
    	hash_ctl.keysize = MAXALIGN(sizeof(BMBuildHashKey)) +
                           MAXALIGN(sizeof(Datum) * cur_bmbuild->natts) +
                           MAXALIGN(sizeof(bool) * cur_bmbuild->natts);

		hash_ctl.entrysize = hash_ctl.keysize + sizeof(BMBuildLovData) + 200; 
    	hash_ctl.hash = build_hash_key;
	    hash_ctl.match = build_match_key;
	    hash_ctl.keycopy = build_keycopy;
    	hash_ctl.hcxt = AllocSetContextCreate(CurrentMemoryContext,
        	                      "Bitmap build hash table",
            	                  ALLOCSET_DEFAULT_MINSIZE,
                	              ALLOCSET_DEFAULT_INITSIZE,
                    	          ALLOCSET_DEFAULT_MAXSIZE);
		cur_bmbuild->hash_cxt = hash_ctl.hcxt;

		hash_flags = HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT | HASH_KEYCOPY;

		bmstate->lovitem_hash = hash_create("Bitmap index build lov item hash",
											100, &hash_ctl, hash_flags);
        bmstate->lovitem_hashKeySize = hash_ctl.keysize;
	}
	else
	{
		int attno;
		bmstate->lovitem_hash = NULL;
		bmstate->lovitem_hashKeySize = 0;
		bmstate->bm_lov_scanKeys =
			(ScanKey)palloc0(bmstate->bm_tupDesc->natts * sizeof(ScanKeyData));

		for (attno = 0; attno < bmstate->bm_tupDesc->natts; attno++)
		{
			RegProcedure	opfuncid;
			Oid				atttypid;

			atttypid = bmstate->bm_tupDesc->attrs[attno]->atttypid;
			opfuncid = equality_oper_funcid(atttypid);

			ScanKeyEntryInitialize(&(bmstate->bm_lov_scanKeys[attno]), SK_ISNULL, 
							   attno + 1, BTEqualStrategyNumber, InvalidOid, 
							   opfuncid, 0);
		}

		bmstate->bm_lov_scanDesc = index_beginscan(bmstate->bm_lov_heap,
							 bmstate->bm_lov_index, ActiveSnapshot, 
							 bmstate->bm_tupDesc->natts,
							 bmstate->bm_lov_scanKeys);
	}

	/*
	 * We need to log index creation in WAL iff WAL archiving is enabled
	 * AND it's not a temp index. Currently, since building an index
	 * writes page to the shared buffer, we can't disable WAL archiving.
	 * We will add this shortly.
	 */	
	bmstate->use_wal = !XLog_UnconvertedCanBypassWal() && !index->rd_istemp;
}