LTP GCOV extension - code coverage report
Current view: directory - access/gin - ginscan.c
Test: unnamed
Date: 2008-07-03 Instrumented lines: 114
Code covered: 71.1 % Executed lines: 81
Legend: not executed executed

       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * ginscan.c
       4                 :  *        routines to manage scans inverted index relations
       5                 :  *
       6                 :  *
       7                 :  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
       8                 :  * Portions Copyright (c) 1994, Regents of the University of California
       9                 :  *
      10                 :  * IDENTIFICATION
      11                 :  *                      $PostgreSQL: pgsql/src/backend/access/gin/ginscan.c,v 1.11 2007/11/15 21:14:31 momjian Exp $
      12                 :  *-------------------------------------------------------------------------
      13                 :  */
      14                 : 
      15                 : #include "postgres.h"
      16                 : #include "access/genam.h"
      17                 : #include "access/gin.h"
      18                 : #include "pgstat.h"
      19                 : #include "utils/memutils.h"
      20                 : 
      21                 : 
      22                 : Datum
      23                 : ginbeginscan(PG_FUNCTION_ARGS)
      24              26 : {
      25              26 :         Relation        rel = (Relation) PG_GETARG_POINTER(0);
      26              26 :         int                     keysz = PG_GETARG_INT32(1);
      27              26 :         ScanKey         scankey = (ScanKey) PG_GETARG_POINTER(2);
      28                 :         IndexScanDesc scan;
      29                 : 
      30              26 :         scan = RelationGetIndexScan(rel, keysz, scankey);
      31                 : 
      32              26 :         PG_RETURN_POINTER(scan);
      33                 : }
      34                 : 
      35                 : static void
      36                 : fillScanKey(GinState *ginstate, GinScanKey key, Datum query,
      37                 :                         Datum *entryValues, uint32 nEntryValues, StrategyNumber strategy)
      38              26 : {
      39                 :         uint32          i,
      40                 :                                 j;
      41                 : 
      42              26 :         key->nentries = nEntryValues;
      43              26 :         key->entryRes = (bool *) palloc0(sizeof(bool) * nEntryValues);
      44              26 :         key->scanEntry = (GinScanEntry) palloc(sizeof(GinScanEntryData) * nEntryValues);
      45              26 :         key->strategy = strategy;
      46              26 :         key->query = query;
      47              26 :         key->firstCall = TRUE;
      48              26 :         ItemPointerSet(&(key->curItem), InvalidBlockNumber, InvalidOffsetNumber);
      49                 : 
      50              80 :         for (i = 0; i < nEntryValues; i++)
      51                 :         {
      52              54 :                 key->scanEntry[i].pval = key->entryRes + i;
      53              54 :                 key->scanEntry[i].entry = entryValues[i];
      54              54 :                 ItemPointerSet(&(key->scanEntry[i].curItem), InvalidBlockNumber, InvalidOffsetNumber);
      55              54 :                 key->scanEntry[i].offset = InvalidOffsetNumber;
      56              54 :                 key->scanEntry[i].buffer = InvalidBuffer;
      57              54 :                 key->scanEntry[i].list = NULL;
      58              54 :                 key->scanEntry[i].nlist = 0;
      59                 : 
      60                 :                 /* link to the equals entry in current scan key */
      61              54 :                 key->scanEntry[i].master = NULL;
      62             101 :                 for (j = 0; j < i; j++)
      63              47 :                         if (compareEntries(ginstate, entryValues[i], entryValues[j]) == 0)
      64                 :                         {
      65               0 :                                 key->scanEntry[i].master = key->scanEntry + j;
      66               0 :                                 break;
      67                 :                         }
      68                 :         }
      69              26 : }
      70                 : 
      71                 : #ifdef NOT_USED
      72                 : 
      73                 : static void
      74                 : resetScanKeys(GinScanKey keys, uint32 nkeys)
      75                 : {
      76                 :         uint32          i,
      77                 :                                 j;
      78                 : 
      79                 :         if (keys == NULL)
      80                 :                 return;
      81                 : 
      82                 :         for (i = 0; i < nkeys; i++)
      83                 :         {
      84                 :                 GinScanKey      key = keys + i;
      85                 : 
      86                 :                 key->firstCall = TRUE;
      87                 :                 ItemPointerSet(&(key->curItem), InvalidBlockNumber, InvalidOffsetNumber);
      88                 : 
      89                 :                 for (j = 0; j < key->nentries; j++)
      90                 :                 {
      91                 :                         if (key->scanEntry[j].buffer != InvalidBuffer)
      92                 :                                 ReleaseBuffer(key->scanEntry[i].buffer);
      93                 : 
      94                 :                         ItemPointerSet(&(key->scanEntry[j].curItem), InvalidBlockNumber, InvalidOffsetNumber);
      95                 :                         key->scanEntry[j].offset = InvalidOffsetNumber;
      96                 :                         key->scanEntry[j].buffer = InvalidBuffer;
      97                 :                         key->scanEntry[j].list = NULL;
      98                 :                         key->scanEntry[j].nlist = 0;
      99                 :                 }
     100                 :         }
     101                 : }
     102                 : #endif
     103                 : 
     104                 : static void
     105                 : freeScanKeys(GinScanKey keys, uint32 nkeys, bool removeRes)
     106              60 : {
     107                 :         uint32          i,
     108                 :                                 j;
     109                 : 
     110              60 :         if (keys == NULL)
     111              34 :                 return;
     112                 : 
     113              52 :         for (i = 0; i < nkeys; i++)
     114                 :         {
     115              26 :                 GinScanKey      key = keys + i;
     116                 : 
     117              80 :                 for (j = 0; j < key->nentries; j++)
     118                 :                 {
     119              54 :                         if (key->scanEntry[j].buffer != InvalidBuffer)
     120               0 :                                 ReleaseBuffer(key->scanEntry[j].buffer);
     121              54 :                         if (removeRes && key->scanEntry[j].list)
     122              48 :                                 pfree(key->scanEntry[j].list);
     123                 :                 }
     124                 : 
     125              26 :                 if (removeRes)
     126              26 :                         pfree(key->entryRes);
     127              26 :                 pfree(key->scanEntry);
     128                 :         }
     129                 : 
     130              26 :         pfree(keys);
     131                 : }
     132                 : 
     133                 : void
     134                 : newScanKey(IndexScanDesc scan)
     135              26 : {
     136              26 :         ScanKey         scankey = scan->keyData;
     137              26 :         GinScanOpaque so = (GinScanOpaque) scan->opaque;
     138                 :         int                     i;
     139              26 :         uint32          nkeys = 0;
     140                 : 
     141              26 :         so->keys = (GinScanKey) palloc(scan->numberOfKeys * sizeof(GinScanKeyData));
     142                 : 
     143              26 :         if (scan->numberOfKeys < 1)
     144               0 :                 ereport(ERROR,
     145                 :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     146                 :                                  errmsg("GIN indexes do not support whole-index scans")));
     147                 : 
     148              26 :         so->isVoidRes = false;
     149                 : 
     150              52 :         for (i = 0; i < scan->numberOfKeys; i++)
     151                 :         {
     152                 :                 Datum      *entryValues;
     153                 :                 int32           nEntryValues;
     154                 : 
     155              26 :                 if (scankey[i].sk_flags & SK_ISNULL)
     156               0 :                         elog(ERROR, "Gin doesn't support NULL as scan key");
     157                 :                 Assert(scankey[i].sk_attno == 1);
     158                 : 
     159              26 :                 entryValues = (Datum *) DatumGetPointer(
     160                 :                                                                                                 FunctionCall3(
     161                 :                                                                                                 &so->ginstate.extractQueryFn,
     162                 :                                                                                                           scankey[i].sk_argument,
     163                 :                                                                                           PointerGetDatum(&nEntryValues),
     164                 :                                                                            UInt16GetDatum(scankey[i].sk_strategy)
     165                 :                                                                                                                           )
     166                 :                         );
     167              26 :                 if (nEntryValues < 0)
     168                 :                 {
     169                 :                         /*
     170                 :                          * extractQueryFn signals that nothing will be found, so we can
     171                 :                          * just set isVoidRes flag...
     172                 :                          */
     173               0 :                         so->isVoidRes = true;
     174               0 :                         break;
     175                 :                 }
     176              26 :                 if (entryValues == NULL || nEntryValues == 0)
     177                 :                         /* full scan... */
     178                 :                         continue;
     179                 : 
     180              26 :                 fillScanKey(&so->ginstate, &(so->keys[nkeys]), scankey[i].sk_argument,
     181                 :                                         entryValues, nEntryValues, scankey[i].sk_strategy);
     182              26 :                 nkeys++;
     183                 :         }
     184                 : 
     185              26 :         so->nkeys = nkeys;
     186                 : 
     187              26 :         if (so->nkeys == 0 && !so->isVoidRes)
     188               0 :                 ereport(ERROR,
     189                 :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     190                 :                            errmsg("GIN index does not support search with void query")));
     191                 : 
     192              26 :         pgstat_count_index_scan(scan->indexRelation);
     193              26 : }
     194                 : 
     195                 : Datum
     196                 : ginrescan(PG_FUNCTION_ARGS)
     197              30 : {
     198              30 :         IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
     199              30 :         ScanKey         scankey = (ScanKey) PG_GETARG_POINTER(1);
     200                 :         GinScanOpaque so;
     201                 : 
     202              30 :         so = (GinScanOpaque) scan->opaque;
     203                 : 
     204              30 :         if (so == NULL)
     205                 :         {
     206                 :                 /* if called from ginbeginscan */
     207              26 :                 so = (GinScanOpaque) palloc(sizeof(GinScanOpaqueData));
     208              26 :                 so->tempCtx = AllocSetContextCreate(CurrentMemoryContext,
     209                 :                                                                                         "Gin scan temporary context",
     210                 :                                                                                         ALLOCSET_DEFAULT_MINSIZE,
     211                 :                                                                                         ALLOCSET_DEFAULT_INITSIZE,
     212                 :                                                                                         ALLOCSET_DEFAULT_MAXSIZE);
     213              26 :                 initGinState(&so->ginstate, scan->indexRelation);
     214              26 :                 scan->opaque = so;
     215                 :         }
     216                 :         else
     217                 :         {
     218               4 :                 freeScanKeys(so->keys, so->nkeys, TRUE);
     219               4 :                 freeScanKeys(so->markPos, so->nkeys, FALSE);
     220                 :         }
     221                 : 
     222              30 :         so->markPos = so->keys = NULL;
     223                 : 
     224              30 :         if (scankey && scan->numberOfKeys > 0)
     225                 :         {
     226              30 :                 memmove(scan->keyData, scankey,
     227                 :                                 scan->numberOfKeys * sizeof(ScanKeyData));
     228                 :         }
     229                 : 
     230              30 :         PG_RETURN_VOID();
     231                 : }
     232                 : 
     233                 : 
     234                 : Datum
     235                 : ginendscan(PG_FUNCTION_ARGS)
     236              26 : {
     237              26 :         IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
     238              26 :         GinScanOpaque so = (GinScanOpaque) scan->opaque;
     239                 : 
     240              26 :         if (so != NULL)
     241                 :         {
     242              26 :                 freeScanKeys(so->keys, so->nkeys, TRUE);
     243              26 :                 freeScanKeys(so->markPos, so->nkeys, FALSE);
     244                 : 
     245              26 :                 MemoryContextDelete(so->tempCtx);
     246                 : 
     247              26 :                 pfree(so);
     248                 :         }
     249                 : 
     250              26 :         PG_RETURN_VOID();
     251                 : }
     252                 : 
     253                 : static GinScanKey
     254                 : copyScanKeys(GinScanKey keys, uint32 nkeys)
     255               0 : {
     256                 :         GinScanKey      newkeys;
     257                 :         uint32          i,
     258                 :                                 j;
     259                 : 
     260               0 :         newkeys = (GinScanKey) palloc(sizeof(GinScanKeyData) * nkeys);
     261               0 :         memcpy(newkeys, keys, sizeof(GinScanKeyData) * nkeys);
     262                 : 
     263               0 :         for (i = 0; i < nkeys; i++)
     264                 :         {
     265               0 :                 newkeys[i].scanEntry = (GinScanEntry) palloc(sizeof(GinScanEntryData) * keys[i].nentries);
     266               0 :                 memcpy(newkeys[i].scanEntry, keys[i].scanEntry, sizeof(GinScanEntryData) * keys[i].nentries);
     267                 : 
     268               0 :                 for (j = 0; j < keys[i].nentries; j++)
     269                 :                 {
     270               0 :                         if (keys[i].scanEntry[j].buffer != InvalidBuffer)
     271               0 :                                 IncrBufferRefCount(keys[i].scanEntry[j].buffer);
     272               0 :                         if (keys[i].scanEntry[j].master)
     273                 :                         {
     274               0 :                                 int                     masterN = keys[i].scanEntry[j].master - keys[i].scanEntry;
     275                 : 
     276               0 :                                 newkeys[i].scanEntry[j].master = newkeys[i].scanEntry + masterN;
     277                 :                         }
     278                 :                 }
     279                 :         }
     280                 : 
     281               0 :         return newkeys;
     282                 : }
     283                 : 
     284                 : Datum
     285                 : ginmarkpos(PG_FUNCTION_ARGS)
     286               0 : {
     287               0 :         IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
     288               0 :         GinScanOpaque so = (GinScanOpaque) scan->opaque;
     289                 : 
     290               0 :         freeScanKeys(so->markPos, so->nkeys, FALSE);
     291               0 :         so->markPos = copyScanKeys(so->keys, so->nkeys);
     292                 : 
     293               0 :         PG_RETURN_VOID();
     294                 : }
     295                 : 
     296                 : Datum
     297                 : ginrestrpos(PG_FUNCTION_ARGS)
     298               0 : {
     299               0 :         IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
     300               0 :         GinScanOpaque so = (GinScanOpaque) scan->opaque;
     301                 : 
     302               0 :         freeScanKeys(so->keys, so->nkeys, FALSE);
     303               0 :         so->keys = copyScanKeys(so->markPos, so->nkeys);
     304                 : 
     305               0 :         PG_RETURN_VOID();
     306                 : }

Generated by: LTP GCOV extension version 1.5