/* * execTuplesHashPrepare * Look up the equality and hashing functions needed for a TupleHashTable. * * This is similar to execTuplesMatchPrepare, but we also need to find the * hash functions associated with the equality operators. *eqfunctions and * *hashfunctions receive the palloc'd result arrays. */ void execTuplesHashPrepare(TupleDesc tupdesc, int numCols, AttrNumber *matchColIdx, FmgrInfo **eqfunctions, FmgrInfo **hashfunctions) { int i; *eqfunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo)); *hashfunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo)); for (i = 0; i < numCols; i++) { AttrNumber att = matchColIdx[i]; Oid typid = tupdesc->attrs[att - 1]->atttypid; Operator optup; Oid eq_opr; Oid eq_function; Oid hash_function; optup = equality_oper(typid, false); eq_opr = oprid(optup); eq_function = oprfuncid(optup); ReleaseSysCache(optup); hash_function = get_op_hash_function(eq_opr); if (!OidIsValid(hash_function)) /* should not happen */ elog(ERROR, "could not find hash function for hash operator %u", eq_opr); fmgr_info(eq_function, &(*eqfunctions)[i]); fmgr_info(hash_function, &(*hashfunctions)[i]); } }
/* * execTuplesHashPrepare * Look up the equality and hashing functions needed for a TupleHashTable. * * This is similar to execTuplesMatchPrepare, but we also need to find the * hash functions associated with the equality operators. *eqfunctions and * *hashfunctions receive the palloc'd result arrays. */ void execTuplesHashPrepareSGB(TupleDesc tupdesc, int numCols, AttrNumber *matchColIdx, FmgrInfo **eqfunctions, FmgrInfo **hashfunctions, FmgrInfo **ltfunctions, FmgrInfo **minusfunctions) { int i; *eqfunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo)); *hashfunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo)); *ltfunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo)); *minusfunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo)); for (i = 0; i < numCols; i++) { AttrNumber att = matchColIdx[i]; Oid typid = tupdesc->attrs[att - 1]->atttypid; Operator optup; Oid eq_opr; Oid eq_function; Oid hash_function; Oid lt_function; Oid minus_function; /*GIVEN A TYPE GET THE = FUNCTION*/ /*eq_function = equality_oper_funcid(typid);*/ optup = equality_oper(typid, false); eq_opr = oprid(optup); eq_function = oprfuncid(optup); ReleaseSysCache(optup); /*GIVEN A TYPE GET THE HASH FUNCTION*/ hash_function = get_op_hash_function(eq_opr); if (!OidIsValid(hash_function)) /* should not happen */ elog(ERROR, "could not find hash function for hash operator %u", eq_opr); /*GIVEN A TYPE GET THE < FUNCTION*/ optup = ordering_oper(typid, false); lt_function = oprfuncid(optup); ReleaseSysCache(optup); /*GIVEN A TYPE GET THE - FUNCTION*/ optup = minus_oper(typid, false); /*minus_oper WAS ADDED BY YASIN*/ minus_function = oprfuncid(optup); /*get the function from the operator tuple*/ ReleaseSysCache(optup); fmgr_info(eq_function, &(*eqfunctions)[i]); fmgr_info(hash_function, &(*hashfunctions)[i]); fmgr_info(lt_function, &(*ltfunctions)[i]); fmgr_info(minus_function, &(*minusfunctions)[i]); } }
/* * equality_oper_funcid - convenience routine for oprfuncid(equality_oper()) */ Oid equality_oper_funcid(Oid argtype) { Operator optup; Oid result; optup = equality_oper(argtype, false); result = oprfuncid(optup); ReleaseSysCache(optup); return result; }
/* * ordering_oper_opid - convenience routine for oprid(equality_oper()) */ Oid equality_oper_opid(Oid argtype) { Operator optup; Oid result; optup = equality_oper(argtype, false); result = oprid(optup); ReleaseOperator(optup); return result; }
/* * 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; }
/*CHANGED BY YASIN*/ void execTuplesMatchAroundPrepare(TupleDesc tupdesc, int numCols, AttrNumber *matchColIdx, FmgrInfo **eqfunctions, FmgrInfo **ltfunctions, FmgrInfo **minusfunctions) { int i; *eqfunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo)); *ltfunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo)); *minusfunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo)); for (i = 0; i < numCols; i++) { AttrNumber att = matchColIdx[i]; Oid typid = tupdesc->attrs[att - 1]->atttypid; Operator optup; Oid eq_function; Oid lt_function; Oid minus_function; /*GIVEN A TYPE GET THE = FUNCTION*/ /*eq_function = equality_oper_funcid(typid);*/ optup = equality_oper(typid, false); eq_function = oprfuncid(optup); ReleaseSysCache(optup); /*GIVEN A TYPE GET THE < FUNCTION*/ optup = ordering_oper(typid, false); lt_function = oprfuncid(optup); ReleaseSysCache(optup); /*GIVEN A TYPE GET THE - FUNCTION*/ optup = minus_oper(typid, false); /*minus_oper WAS ADDED BY YASIN*/ minus_function = oprfuncid(optup); /*get the function from the operator tuple*/ ReleaseSysCache(optup); fmgr_info(eq_function, &(*eqfunctions)[i]); fmgr_info(lt_function, &(*ltfunctions)[i]); fmgr_info(minus_function, &(*minusfunctions)[i]); } }
/* * _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; }