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