LTP GCOV extension - code coverage report
Current view: directory - access/hash - hashutil.c
Test: unnamed
Date: 2008-07-03 Instrumented lines: 57
Code covered: 66.7 % Executed lines: 38
Legend: not executed executed

       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * hashutil.c
       4                 :  *        Utility code for Postgres hash implementation.
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
       7                 :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :  *
       9                 :  *
      10                 :  * IDENTIFICATION
      11                 :  *        $PostgreSQL: pgsql/src/backend/access/hash/hashutil.c,v 1.52 2007/05/03 16:45:58 tgl Exp $
      12                 :  *
      13                 :  *-------------------------------------------------------------------------
      14                 :  */
      15                 : #include "postgres.h"
      16                 : 
      17                 : #include "access/genam.h"
      18                 : #include "access/hash.h"
      19                 : #include "access/reloptions.h"
      20                 : #include "executor/execdebug.h"
      21                 : #include "utils/lsyscache.h"
      22                 : 
      23                 : 
      24                 : /*
      25                 :  * _hash_checkqual -- does the index tuple satisfy the scan conditions?
      26                 :  */
      27                 : bool
      28                 : _hash_checkqual(IndexScanDesc scan, IndexTuple itup)
      29            4173 : {
      30            4173 :         TupleDesc       tupdesc = RelationGetDescr(scan->indexRelation);
      31            4173 :         ScanKey         key = scan->keyData;
      32            4173 :         int                     scanKeySize = scan->numberOfKeys;
      33                 : 
      34                 :         IncrIndexProcessed();
      35                 : 
      36            8366 :         while (scanKeySize > 0)
      37                 :         {
      38                 :                 Datum           datum;
      39                 :                 bool            isNull;
      40                 :                 Datum           test;
      41                 : 
      42            4173 :                 datum = index_getattr(itup,
      43                 :                                                           key->sk_attno,
      44                 :                                                           tupdesc,
      45                 :                                                           &isNull);
      46                 : 
      47                 :                 /* assume sk_func is strict */
      48            4173 :                 if (isNull)
      49               0 :                         return false;
      50            4173 :                 if (key->sk_flags & SK_ISNULL)
      51               0 :                         return false;
      52                 : 
      53            4173 :                 test = FunctionCall2(&key->sk_func, datum, key->sk_argument);
      54                 : 
      55            4173 :                 if (!DatumGetBool(test))
      56            4153 :                         return false;
      57                 : 
      58              20 :                 key++;
      59              20 :                 scanKeySize--;
      60                 :         }
      61                 : 
      62              20 :         return true;
      63                 : }
      64                 : 
      65                 : /*
      66                 :  * _hash_datum2hashkey -- given a Datum, call the index's hash procedure
      67                 :  *
      68                 :  * The Datum is assumed to be of the index's column type, so we can use the
      69                 :  * "primary" hash procedure that's tracked for us by the generic index code.
      70                 :  */
      71                 : uint32
      72                 : _hash_datum2hashkey(Relation rel, Datum key)
      73           95055 : {
      74                 :         FmgrInfo   *procinfo;
      75                 : 
      76                 :         /* XXX assumes index has only one attribute */
      77           95055 :         procinfo = index_getprocinfo(rel, 1, HASHPROC);
      78                 : 
      79           95055 :         return DatumGetUInt32(FunctionCall1(procinfo, key));
      80                 : }
      81                 : 
      82                 : /*
      83                 :  * _hash_datum2hashkey_type -- given a Datum of a specified type,
      84                 :  *                      hash it in a fashion compatible with this index
      85                 :  *
      86                 :  * This is much more expensive than _hash_datum2hashkey, so use it only in
      87                 :  * cross-type situations.
      88                 :  */
      89                 : uint32
      90                 : _hash_datum2hashkey_type(Relation rel, Datum key, Oid keytype)
      91               0 : {
      92                 :         RegProcedure hash_proc;
      93                 : 
      94                 :         /* XXX assumes index has only one attribute */
      95               0 :         hash_proc = get_opfamily_proc(rel->rd_opfamily[0],
      96                 :                                                                   keytype,
      97                 :                                                                   keytype,
      98                 :                                                                   HASHPROC);
      99               0 :         if (!RegProcedureIsValid(hash_proc))
     100               0 :                 elog(ERROR, "missing support function %d(%u,%u) for index \"%s\"",
     101                 :                          HASHPROC, keytype, keytype,
     102                 :                          RelationGetRelationName(rel));
     103                 : 
     104               0 :         return DatumGetUInt32(OidFunctionCall1(hash_proc, key));
     105                 : }
     106                 : 
     107                 : /*
     108                 :  * _hash_hashkey2bucket -- determine which bucket the hashkey maps to.
     109                 :  */
     110                 : Bucket
     111                 : _hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket,
     112                 :                                          uint32 highmask, uint32 lowmask)
     113           95055 : {
     114                 :         Bucket          bucket;
     115                 : 
     116           95055 :         bucket = hashkey & highmask;
     117           95055 :         if (bucket > maxbucket)
     118           10279 :                 bucket = bucket & lowmask;
     119                 : 
     120           95055 :         return bucket;
     121                 : }
     122                 : 
     123                 : /*
     124                 :  * _hash_log2 -- returns ceil(lg2(num))
     125                 :  */
     126                 : uint32
     127                 : _hash_log2(uint32 num)
     128           38006 : {
     129                 :         uint32          i,
     130                 :                                 limit;
     131                 : 
     132           38006 :         limit = 1;
     133           38006 :         for (i = 0; limit < num; limit <<= 1, i++)
     134                 :                 ;
     135           38006 :         return i;
     136                 : }
     137                 : 
     138                 : /*
     139                 :  * _hash_checkpage -- sanity checks on the format of all hash pages
     140                 :  *
     141                 :  * If flags is not zero, it is a bitwise OR of the acceptable values of
     142                 :  * hasho_flag.
     143                 :  */
     144                 : void
     145                 : _hash_checkpage(Relation rel, Buffer buf, int flags)
     146          127581 : {
     147          127581 :         Page            page = BufferGetPage(buf);
     148                 : 
     149                 :         /*
     150                 :          * ReadBuffer verifies that every newly-read page passes
     151                 :          * PageHeaderIsValid, which means it either contains a reasonably sane
     152                 :          * page header or is all-zero.  We have to defend against the all-zero
     153                 :          * case, however.
     154                 :          */
     155          127581 :         if (PageIsNew(page))
     156               0 :                 ereport(ERROR,
     157                 :                                 (errcode(ERRCODE_INDEX_CORRUPTED),
     158                 :                          errmsg("index \"%s\" contains unexpected zero page at block %u",
     159                 :                                         RelationGetRelationName(rel),
     160                 :                                         BufferGetBlockNumber(buf)),
     161                 :                                  errhint("Please REINDEX it.")));
     162                 : 
     163                 :         /*
     164                 :          * Additionally check that the special area looks sane.
     165                 :          */
     166          127581 :         if (((PageHeader) (page))->pd_special !=
     167                 :                 (BLCKSZ - MAXALIGN(sizeof(HashPageOpaqueData))))
     168               0 :                 ereport(ERROR,
     169                 :                                 (errcode(ERRCODE_INDEX_CORRUPTED),
     170                 :                                  errmsg("index \"%s\" contains corrupted page at block %u",
     171                 :                                                 RelationGetRelationName(rel),
     172                 :                                                 BufferGetBlockNumber(buf)),
     173                 :                                  errhint("Please REINDEX it.")));
     174                 : 
     175          127581 :         if (flags)
     176                 :         {
     177          127581 :                 HashPageOpaque opaque = (HashPageOpaque) PageGetSpecialPointer(page);
     178                 : 
     179          127581 :                 if ((opaque->hasho_flag & flags) == 0)
     180               0 :                         ereport(ERROR,
     181                 :                                         (errcode(ERRCODE_INDEX_CORRUPTED),
     182                 :                                    errmsg("index \"%s\" contains corrupted page at block %u",
     183                 :                                                   RelationGetRelationName(rel),
     184                 :                                                   BufferGetBlockNumber(buf)),
     185                 :                                          errhint("Please REINDEX it.")));
     186                 :         }
     187                 : 
     188                 :         /*
     189                 :          * When checking the metapage, also verify magic number and version.
     190                 :          */
     191          127581 :         if (flags == LH_META_PAGE)
     192                 :         {
     193           40516 :                 HashMetaPage metap = (HashMetaPage) page;
     194                 : 
     195           40516 :                 if (metap->hashm_magic != HASH_MAGIC)
     196               0 :                         ereport(ERROR,
     197                 :                                         (errcode(ERRCODE_INDEX_CORRUPTED),
     198                 :                                          errmsg("index \"%s\" is not a hash index",
     199                 :                                                         RelationGetRelationName(rel))));
     200                 : 
     201           40516 :                 if (metap->hashm_version != HASH_VERSION)
     202               0 :                         ereport(ERROR,
     203                 :                                         (errcode(ERRCODE_INDEX_CORRUPTED),
     204                 :                                          errmsg("index \"%s\" has wrong hash version",
     205                 :                                                         RelationGetRelationName(rel)),
     206                 :                                          errhint("Please REINDEX it.")));
     207                 :         }
     208          127581 : }
     209                 : 
     210                 : Datum
     211                 : hashoptions(PG_FUNCTION_ARGS)
     212               0 : {
     213               0 :         Datum           reloptions = PG_GETARG_DATUM(0);
     214               0 :         bool            validate = PG_GETARG_BOOL(1);
     215                 :         bytea      *result;
     216                 : 
     217               0 :         result = default_reloptions(reloptions, validate,
     218                 :                                                                 HASH_MIN_FILLFACTOR,
     219                 :                                                                 HASH_DEFAULT_FILLFACTOR);
     220               0 :         if (result)
     221               0 :                 PG_RETURN_BYTEA_P(result);
     222               0 :         PG_RETURN_NULL();
     223                 : }

Generated by: LTP GCOV extension version 1.5