home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / access / common / indextuple.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  13.1 KB  |  563 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    indextuple.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    This file contains index tuple accessor and mutator
  7.  *    routines, as well as a few various tuple utilities.
  8.  *
  9.  *   INTERFACE ROUTINES
  10.  *    index_formtuple
  11.  *    index_getsysattr
  12.  *    index_getattr
  13.  *
  14.  *   NOTES
  15.  *    All the stupid ``GeneralResultXXX'' routines should be
  16.  *    eliminated and replaced with something simple and clean.
  17.  *    
  18.  *    old routines formituple, FormIndexTuple, AMgetattr have been
  19.  *    turned into macros in itup.h.  IsValid predicates have been
  20.  *    macroized too. -cim 4/30/91
  21.  *    
  22.  *   IDENTIFICATION
  23.  *    $Header: /private/postgres/src/access/common/RCS/indextuple.c,v 1.14 1992/04/03 01:01:45 mer Exp $
  24.  * ----------------------------------------------------------------
  25.  */
  26. #include "tmp/c.h"
  27. #include "access/ibit.h"
  28. #include "access/itup.h"
  29. #include "access/tupdesc.h"
  30. #include "access/attval.h"
  31. #include "access/tupmacs.h"
  32.  
  33. #include "storage/form.h"
  34. #include "storage/itemptr.h"
  35. #include "rules/rlock.h"
  36.  
  37. #include "utils/log.h"
  38. #include "utils/palloc.h"
  39.  
  40. RcsId("$Header: /private/postgres/src/access/common/RCS/indextuple.c,v 1.14 1992/04/03 01:01:45 mer Exp $");
  41.  
  42. /* ----------------------------------------------------------------
  43.  *          index_ tuple interface routines
  44.  * ----------------------------------------------------------------
  45.  */
  46.  
  47. /* ----------------
  48.  *    index_formtuple
  49.  * ----------------
  50.  */
  51. IndexTuple
  52. index_formtuple(numberOfAttributes, tupleDescriptor, value, null)
  53.     AttributeNumber    numberOfAttributes;
  54.     TupleDescriptor    tupleDescriptor;
  55.     Datum        value[];
  56.     char        null[];
  57. {
  58.     register char    *tp;    /* tuple pointer */
  59.     IndexTuple        tuple;    /* return tuple */
  60.     Size        size, hoff;
  61.     int         i, infomask = 0;
  62.     bool        hasnull = false;
  63.     char        tupmask = 0;
  64.  
  65.     if (numberOfAttributes > MaxIndexAttributeNumber)
  66.     elog(WARN, "index_formtuple: numberOfAttributes of %d > %d",
  67.          numberOfAttributes, MaxIndexAttributeNumber);
  68.     
  69.  
  70.     for (i = 0; i < numberOfAttributes && !hasnull; i++)
  71.     {
  72.     if (null[i] != ' ') hasnull = true;
  73.     }
  74.  
  75.     if (hasnull) infomask |= INDEX_NULL_MASK;
  76.  
  77.     hoff = IndexInfoFindDataOffset(infomask);
  78.     size = hoff
  79.      + ComputeDataSize(numberOfAttributes, tupleDescriptor, value, null);
  80.     size = LONGALIGN(size);
  81.  
  82.     tp = (char *) palloc(size);
  83.     tuple = (IndexTuple) tp;
  84.     bzero(tp, (int)size);
  85.     
  86.     DataFill((Pointer) tp + hoff,
  87.          numberOfAttributes,
  88.          tupleDescriptor,
  89.          value,
  90.          null,
  91.          &tupmask,
  92.          (hasnull ? tp + sizeof *tuple : NULL));
  93.  
  94.     /*
  95.      * We do this because DataFill wants to initialize a "tupmask" which
  96.      * is used for HeapTuples, but we want an indextuple infomask.  The only
  97.      * "relevent" info is the "has variable attributes" field, which is in
  98.      * mask position 0x02.  We have already set the null mask above.
  99.      */
  100.  
  101.     if (tupmask & 0x02) infomask |= INDEX_VAR_MASK;
  102.  
  103.     /*
  104.      * Here we make sure that we can actually hold the size.  We also want
  105.      * to make sure that size is not aligned oddly.  This actually is a
  106.      * rather odd way to make sure the size is not too large overall.
  107.      */
  108.  
  109.     if (size & 0xE000)
  110.     {
  111.     elog(WARN, "index_formtuple: data takes %d bytes: too big", size);
  112.     }
  113.  
  114.     infomask |= size;
  115.  
  116.     /* ----------------
  117.      * initialize metadata
  118.      * ----------------
  119.      */
  120.     tuple->t_info = infomask;
  121.     return (tuple);
  122. }
  123.  
  124. /* ----------------
  125.  *    fastgetiattr
  126.  *
  127.  *    This is a newer version of fastgetiattr which attempts to be
  128.  *    faster by caching attribute offsets in the attribute descriptor.
  129.  *
  130.  *    an alternate way to speed things up would be to cache offsets
  131.  *    with the tuple, but that seems more difficult unless you take
  132.  *    the storage hit of actually putting those offsets into the
  133.  *    tuple you send to disk.  Yuck.
  134.  *
  135.  *    This scheme will be slightly slower than that, but should
  136.  *    preform well for queries which hit large #'s of tuples.  After
  137.  *    you cache the offsets once, examining all the other tuples using
  138.  *    the same attribute descriptor will go much quicker. -cim 5/4/91
  139.  * ----------------
  140.  */
  141.  
  142. char *
  143. fastgetiattr(tup, attnum, att, isnull)
  144.     IndexTuple    tup;
  145.     unsigned    attnum;
  146.     struct    attribute *att[];
  147.     bool    *isnull;
  148. {
  149.     register char        *tp;        /* ptr to att in tuple */
  150.     register char        *bp;        /* ptr to att in tuple */
  151.     int             slow;        /* do we have to walk nulls? */
  152.     register int        data_off;    /* tuple data offset */
  153.  
  154.     /* ----------------
  155.      *    sanity checks
  156.      * ----------------
  157.      */
  158.  
  159.     Assert(PointerIsValid(isnull));
  160.     Assert(attnum > 0);
  161.  
  162.     /* ----------------
  163.      *   Three cases:
  164.      * 
  165.      *   1: No nulls and no variable length attributes.
  166.      *   2: Has a null or a varlena AFTER att.
  167.      *   3: Has nulls or varlenas BEFORE att.
  168.      * ----------------
  169.      */
  170.  
  171.     *isnull =  false;
  172.     data_off = IndexTupleHasMinHeader(tup) ? sizeof *tup : 
  173.                IndexInfoFindDataOffset(tup->t_info);
  174.  
  175.     if (IndexTupleNoNulls(tup))
  176.     {
  177.     /* first attribute is always at position zero */
  178.  
  179.     if (attnum == 1)
  180.     {
  181.          return(fetchatt(att, (Pointer) tup + data_off));
  182.     }
  183.     attnum--;
  184.  
  185.     if (att[attnum]->attcacheoff > 0)
  186.     {
  187.         return(fetchatt(att + attnum, (Pointer) tup + data_off
  188.                 + att[attnum]->attcacheoff));
  189.     }
  190.  
  191.     tp = (Pointer) tup + data_off;
  192.  
  193.     slow = 0;
  194.     }
  195.     else /* there's a null somewhere in the tuple */
  196.     {
  197.     bp = (char *) tup + sizeof(*tup); /* "knows" t_bits are here! */
  198.     slow = 0;
  199.         /* ----------------
  200.          *    check to see if desired att is null
  201.          * ----------------
  202.          */
  203.  
  204.     attnum--;
  205.     {
  206.         if (att_isnull(attnum, bp)) 
  207.         {
  208.         *isnull = true;
  209.         return NULL;
  210.         }
  211.     }
  212.         /* ----------------
  213.      *      Now check to see if any preceeding bits are null...
  214.          * ----------------
  215.      */
  216.     {
  217.         register int  i = 0; /* current offset in bp */
  218.         register int  mask;     /* bit in byte we're looking at */
  219.         register char n;     /* current byte in bp */
  220.         register int byte, finalbit;
  221.     
  222.         byte = attnum >> 3;
  223.         finalbit = attnum & 0x07;
  224.  
  225.         for (; i <= byte; i++) {
  226.             n = bp[i];
  227.             if (i < byte) {
  228.             /* check for nulls in any "earlier" bytes */
  229.             if ((~n) != 0) {
  230.                 slow++;
  231.                 break;
  232.             }
  233.             } else {
  234.             /* check for nulls "before" final bit of last byte*/
  235.             mask = (finalbit << 1) - 1;
  236.             if ((~n) & mask)
  237.                 slow++;
  238.             }
  239.         }
  240.         }
  241.     tp = (Pointer) tup + data_off;
  242.     }
  243.  
  244.     /* now check for any non-fixed length attrs before our attribute */
  245.  
  246.     if (!slow)
  247.     {
  248.     if (att[attnum]->attcacheoff > 0)
  249.     {
  250.         return(fetchatt(att + attnum, tp + att[attnum]->attcacheoff));
  251.     }
  252.     else if (!IndexTupleAllFixed(tup))
  253.     {
  254.         register int j = 0;
  255.  
  256.         for (j = 0; j < attnum && !slow; j++)
  257.         if (att[j]->attlen < 1) slow = 1;
  258.     }
  259.     }
  260.  
  261.     /*
  262.      * if slow is zero, and we got here, we know that we have a tuple with
  263.      * no nulls.  We also know that we have to initialize the remainder of
  264.      * the attribute cached offset values.
  265.      */
  266.  
  267.     if (!slow)
  268.     {
  269.     register int j = 1;
  270.     register long off;
  271.  
  272.     /*
  273.      * need to set cache for some atts
  274.      */
  275.  
  276.     att[0]->attcacheoff = 0;
  277.  
  278.     while (att[j]->attcacheoff > 0) j++;
  279.  
  280.     off = att[j-1]->attcacheoff + att[j-1]->attlen;
  281.  
  282.     for (; j < attnum + 1; j++)
  283.     {
  284.         /*
  285.          * Fix me when going to a machine with more than a four-byte
  286.          * word!
  287.          */
  288.  
  289.         switch(att[j]->attlen)
  290.         {
  291.         case sizeof(char) : break;
  292.         case sizeof(short): off = SHORTALIGN(off); break;
  293.         default           : off = LONGALIGN(off); break;
  294.         }
  295.  
  296.         att[j]->attcacheoff = off;
  297.         off += att[j]->attlen;
  298.     }
  299.  
  300.     return(fetchatt(att + attnum, tp + att[attnum]->attcacheoff));
  301.     }
  302.     else
  303.     {
  304.     register bool usecache = true;
  305.     register int off = 0;
  306.     register int savelen;
  307.     register int i;
  308.  
  309.     /*
  310.      * Now we know that we have to walk the tuple CAREFULLY.
  311.      */
  312.     
  313.     for (i = 0; i < attnum; i++)
  314.     {
  315.         if (!IndexTupleNoNulls(tup))
  316.         {
  317.         if (att_isnull(i, bp))
  318.         {
  319.             usecache = false;
  320.             continue;
  321.         }
  322.         }
  323.  
  324.         if (usecache && att[i]->attcacheoff > 0)
  325.         {
  326.         off = att[i]->attcacheoff;
  327.         if (att[i]->attlen == -1)
  328.         {
  329.             usecache = false;
  330.         }
  331.         else continue;
  332.         }
  333.  
  334.         if (usecache) att[i]->attcacheoff = off;
  335.         switch(att[i]->attlen)
  336.         {
  337.             case sizeof(char):
  338.                 off++;
  339.                 break;
  340.             case sizeof(short):
  341.                 off = SHORTALIGN(off + sizeof(short));
  342.                 break;
  343.             case -1:
  344.                 usecache = false;
  345.             off = LONGALIGN(off);
  346.                 off += VARSIZE(tp + off);
  347.             break;
  348.         default:
  349.             off = LONGALIGN(off + att[i]->attlen);
  350.             break;
  351.         }
  352.     }
  353.  
  354.     return(fetchatt(att + attnum, tp + off));
  355.     }
  356. }
  357. /* ----------------
  358.  *    index_getsysattr
  359.  * ----------------
  360.  */
  361. AttributeValue
  362. index_getsysattr(tuple, attributeNumber)
  363.     IndexTuple        tuple;
  364.     int            attributeNumber;
  365. {
  366.     static Datum    datum;
  367.     
  368.     switch (attributeNumber) {
  369.     case IndxRuleLockAttributeNumber:
  370.     elog(NOTICE, "index_getsysattr: Rule locks are always NULL");
  371.     return PointerGetDatum((Pointer) NULL);
  372.     break;
  373.     
  374.     case IndxBaseTupleIdAttributeNumber:
  375.     bcopy((char *) &tuple->t_tid, (char *) &datum, sizeof datum);
  376.     return datum;
  377.     break;
  378.     
  379.     default:
  380.     elog(WARN, "IndexTupleGetAttributeValue: undefined attnum %d",
  381.          attributeNumber);
  382.     }
  383.     return((AttributeValue) NULL);
  384. }
  385.  
  386. /* ----------------
  387.  *    index_getattr
  388.  * ----------------
  389.  */
  390. AttributeValue
  391. IndexTupleGetAttributeValue(tuple, attNum, tupleDescriptor, isNullOutP)
  392.     IndexTuple        tuple;
  393.     AttributeNumber        attNum;
  394.     TupleDescriptor    tupleDescriptor;
  395.     Boolean        *isNullOutP;
  396. {
  397.     /* ----------------
  398.      *    handle normal attributes
  399.      * ----------------
  400.      */
  401.     if (attNum > 0)
  402.     return (AttributeValue)
  403.         fastgetiattr(tuple, attNum, tupleDescriptor, isNullOutP);
  404.  
  405.     /* ----------------
  406.      *    otherwise handle system attributes
  407.      * ----------------
  408.      */
  409.     *isNullOutP = '\0';
  410.     return
  411.     index_getsysattr(tuple, attNum);
  412. }
  413.  
  414. Pointer
  415. index_getattr(tuple, attNum, tupDesc, isNullOutP)
  416.     IndexTuple        tuple;
  417.     AttributeNumber    attNum;
  418.     TupleDescriptor    tupDesc;
  419.     Boolean        *isNullOutP;
  420. {
  421.     Datum  datum;
  422.     datum = IndexTupleGetAttributeValue(tuple, attNum, tupDesc, isNullOutP);
  423.     
  424.     return
  425.     DatumGetPointer(datum);
  426. }
  427.  
  428. /* ----------------------------------------------------------------
  429.  *          misc index result stuff (XXX OBSOLETE ME!)
  430.  * ----------------------------------------------------------------
  431.  */
  432.  
  433. GeneralInsertIndexResult
  434. ItemPointerFormGeneralInsertIndexResult(pointer, lock)
  435.     ItemPointer    pointer;
  436.     RuleLock    lock;
  437. {
  438.     GeneralInsertIndexResult    result;
  439.  
  440.     Assert(ItemPointerIsValid(pointer));
  441.     /* XXX Assert(RuleLockIsValid(lock)); locks don't work yet */
  442.  
  443.     result = (GeneralInsertIndexResult) palloc(sizeof *result);
  444.  
  445.     result->pointerData = *pointer;
  446.     result->lock = lock;
  447.     return (result);
  448. }
  449.  
  450. InsertIndexResult
  451. ItemPointerFormInsertIndexResult(pointer, lock, offset)
  452.     ItemPointer    pointer;
  453.     RuleLock    lock;
  454.     double        offset;
  455. {
  456.     InsertIndexResult    result;
  457.  
  458.     Assert(ItemPointerIsValid(pointer));
  459.     /* XXX Assert(RuleLockIsValid(lock)); locks don't work yet */
  460.     /* Assert(InsertOffsetIsValid(offset)); */
  461.  
  462.     result = (InsertIndexResult) palloc(sizeof *result);
  463.  
  464.     result->pointerData = *pointer;
  465.     result->lock = lock;
  466.     result->offset = offset;
  467.     return (result);
  468. }
  469.  
  470. GeneralRetrieveIndexResult
  471. ItemPointerFormGeneralRetrieveIndexResult(heapItemPointer)
  472.     ItemPointer    heapItemPointer;
  473. {
  474.     GeneralRetrieveIndexResult    result;
  475.     Assert(ItemPointerIsValid(heapItemPointer));
  476.  
  477.     result = (GeneralRetrieveIndexResult) palloc(sizeof *result);
  478.     result->heapItemData = *heapItemPointer;
  479.     return (result);
  480. }
  481.  
  482.  
  483. RetrieveIndexResult
  484. ItemPointerFormRetrieveIndexResult(indexItemPointer, heapItemPointer)
  485.     ItemPointer    indexItemPointer;
  486.     ItemPointer    heapItemPointer;
  487. {
  488.     RetrieveIndexResult    result;
  489.  
  490.     Assert(ItemPointerIsValid(indexItemPointer));
  491.     Assert(ItemPointerIsValid(heapItemPointer));
  492.  
  493.     result = (RetrieveIndexResult) palloc(sizeof *result);
  494.  
  495.     result->indexItemData = *indexItemPointer;
  496.     result->heapItemData = *heapItemPointer;
  497.  
  498.     return (result);
  499. }
  500.  
  501. /*
  502.  * Takes an infomask as argument (primarily because this needs to be usable
  503.  * at index_formtuple time so enough space is allocated).
  504.  *
  505.  * Change me if adding an attribute to IndexTuples!!!!!!!!!!!
  506.  */
  507.  
  508. Size
  509. IndexInfoFindDataOffset(t_info)
  510.  
  511. unsigned short t_info;
  512.  
  513. {
  514.     if (!(t_info & (INDEX_NULL_MASK | INDEX_RULE_MASK)))
  515.     return((Size) sizeof(IndexTupleData));
  516.     else
  517.     {
  518.     Size size = sizeof(IndexTupleData);
  519.  
  520.     if (t_info & INDEX_NULL_MASK)
  521.     {
  522.         size += sizeof(IndexAttributeBitMapData);
  523.     }
  524.     if (t_info & INDEX_RULE_MASK)
  525.     {
  526.         size = LONGALIGN(size) + sizeof(IndexTupleRuleLock) + sizeof(char);
  527.     }
  528.     return(LONGALIGN(size));
  529.     }
  530. }
  531.  
  532. /*
  533.  * Copies source into target.  If *target == NULL, we palloc space; otherwise
  534.  * we assume we have space that is already palloc'ed.
  535.  */
  536.  
  537. void
  538. CopyIndexTuple(source, target)
  539.  
  540. IndexTuple source, *target;
  541.  
  542. {
  543.     Size size, hoff;
  544.     IndexTuple ret;
  545.  
  546.     size = IndexTupleSize(source);
  547.     if (*target == NULL)
  548.     {
  549.     *target = ret = (IndexTuple) palloc(size);
  550.     }
  551.  
  552.     bcopy(source, ret, size);
  553. }
  554.  
  555. /*
  556.     for debugging purpose only.  will only be called in dbx.
  557. */
  558. int
  559. indexTupleHeaderSize()
  560. {
  561.     return(sizeof(IndexTupleData));
  562. }
  563.