home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / planner / sys / plancat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  14.4 KB  |  487 lines

  1. /*
  2.  * plancat.c --
  3.  *    C routines needed by the planner (e.g., routines for accessing the
  4.  *    system catalogs).
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include "tmp/postgres.h"
  9.  
  10. RcsId("$Header: /private/postgres/src/planner/sys/RCS/plancat.c,v 1.16 1992/07/30 18:47:04 mao Exp $");
  11.  
  12. #include "access/heapam.h"
  13. #include "access/htup.h"
  14. #include "access/itup.h"
  15. #include "access/tqual.h"
  16. #include "parser/parsetree.h"
  17. #include "utils/fmgr.h"
  18. #include "utils/log.h"
  19.  
  20. #include "nodes/pg_lisp.h"
  21.  
  22. #include "catalog/catname.h"
  23. #include "catalog/syscache.h"
  24. #include "catalog/pg_amop.h"
  25. #include "catalog/pg_index.h"
  26. #include "catalog/pg_inherits.h"
  27. #include "catalog/pg_version.h"
  28.  
  29. /*
  30.  *    RelationCatalogInformation
  31.  *
  32.  *    Given the relid of a relation, retrieve into the array
  33.  *    'relationCatalogInfo' the following information:
  34.  *        whether the relation has secondary indices
  35.  *        number of pages 
  36.  *        number of tuples
  37.  * 
  38.  *        relation-info
  39.  *    
  40.  *        Retrieves catalog information for a given relation.
  41.  *    
  42.  *        Returns a list containing relhasindex, relpages, and reltuples.
  43.  *    
  44.  */
  45.  
  46. /*  .. get_rel
  47.  */
  48.  
  49. LispValue
  50. relation_info (relid)
  51.     Index    relid;
  52. {
  53.     HeapTuple        relationTuple;
  54.     RelationTupleForm    relation;
  55.     int32            rel_info[3];
  56.     LispValue        retval = LispNil;
  57.     int             i;
  58.     ObjectId         relationObjectId;
  59.  
  60.     extern    LispValue _query_range_table_;
  61.  
  62.     relationObjectId = 
  63.       (ObjectId)CInteger(getrelid ( relid, _query_range_table_ ));
  64.     relationTuple = SearchSysCacheTuple(RELOID, (char *) relationObjectId,
  65.                         (char *) NULL, (char *) NULL,
  66.                         (char *) NULL);
  67.     if (HeapTupleIsValid(relationTuple)) {
  68.         relation = (RelationTupleForm)GETSTRUCT(relationTuple);
  69.         rel_info[0] = (relation->relhasindex) ? 1 : 0;
  70.         rel_info[1] = relation->relpages;
  71.         rel_info[2] = relation->reltuples;
  72.     } else
  73.         elog(WARN, "RelationCatalogInformation: Relation %d not found",
  74.              relationObjectId);
  75.     for(i=2; i>=0 ; --i) 
  76.         retval = lispCons(lispInteger(rel_info[i]),retval);
  77.     return(retval);
  78.  
  79. }
  80.  
  81. /* 
  82.  *    IndexCatalogInformation
  83.  *
  84.  *     Returns index info in array 'indexCatalogInfo' in the following order:
  85.  *        OID of the index relation
  86.  *            (NOT the OID of the relation being indexed)
  87.  *        the number of pages in the index relation
  88.  *        the number of tuples in the index relation
  89.  *        the 8 keys of the index
  90.  *        the 8 ordering operators of the index
  91.  *        the 8 classes of the AM operators of the index
  92.  *        TOTAL: 27 long words.
  93.  *
  94.  *    On the first call to this routine, the index relation is opened.
  95.  *    Successive calls will return subsequent indices until no more
  96.  *    are found.
  97.  *
  98.  *    Returns 1 if an index was found, and 0 otherwise.
  99.  */
  100.  
  101. int32
  102. IndexCatalogInformation(notFirst, indrelid, isarchival, indexCatalogInfo)
  103.     int32        notFirst;
  104.     ObjectId    indrelid;        /* indexED relation */
  105.     Boolean        isarchival;        /* XXX not used YET */
  106.     int32        indexCatalogInfo[];
  107. {
  108.     register        i;
  109.     HeapTuple        indexTuple, amopTuple;
  110.     IndexTupleForm        index;
  111.     Relation        indexRelation;
  112.     uint16            amstrategy;    /* XXX not used YET */
  113.     ObjectId        relam;
  114.     static Relation        relation = (Relation) NULL;
  115.     static HeapScanDesc    scan = (HeapScanDesc) NULL;
  116.     static ScanKeyEntryData    indexKey[1] = {
  117.         { 0, IndexHeapRelationIdAttributeNumber, F_OIDEQ }
  118.     };
  119.  
  120.     fmgr_info(F_OIDEQ, &indexKey[0].func, &indexKey[0].nargs);
  121.  
  122.     bzero((char *) indexCatalogInfo, (unsigned) (28 * sizeof(int32)));
  123.  
  124.     /* Find an index on the given relation */
  125.     if (notFirst == 0) {
  126.         if (RelationIsValid(relation))
  127.             RelationCloseHeapRelation(relation);
  128.         if (HeapScanIsValid(scan))
  129.             HeapScanEnd(scan);
  130.         indexKey[0].argument = ObjectIdGetDatum(indrelid);
  131.         relation = RelationNameOpenHeapRelation(IndexRelationName);
  132.         scan = RelationBeginHeapScan(relation, 0, NowTimeQual,
  133.                          1, (ScanKey) indexKey);
  134.     }
  135.     if (!HeapScanIsValid(scan))
  136.         elog(WARN, "IndexCatalogInformation: scan not started");
  137.     indexTuple = HeapScanGetNextTuple(scan, 0, (Buffer *) NULL);
  138.     if (!HeapTupleIsValid(indexTuple)) {
  139.         HeapScanEnd(scan);
  140.         RelationCloseHeapRelation(relation);
  141.         scan = (HeapScanDesc) NULL;
  142.         relation = (Relation) NULL;
  143.         return(0);
  144.     }
  145.  
  146.     /* Extract info from the index tuple */
  147.     index = (IndexTupleForm)GETSTRUCT(indexTuple);
  148.     indexCatalogInfo[0] = index->indexrelid;    /* index relation */
  149.     for (i = 0; i < 8; ++i)                    /* 3-10 */
  150.         indexCatalogInfo[i+3] = index->indkey[i];
  151.     for (i = 0; i < 8; ++i)                    /* 19-26 */
  152.         indexCatalogInfo[i+19] = index->indclass[i];
  153.     
  154.     /* functional index ?? */
  155.     indexCatalogInfo[27] = index->indproc;            /* 27 */
  156.  
  157.     /* Extract info from the relation descriptor for the index */
  158.     indexRelation = (Relation) index_open(index->indexrelid);
  159. #ifdef notdef
  160.     /* XXX should iterate through strategies -- but how?  use #1 for now */
  161.     amstrategy = indexRelation->rd_am->amstrategies;
  162. #endif notdef
  163.     amstrategy = 1;
  164.     relam = indexRelation->rd_rel->relam;
  165.     indexCatalogInfo[1] = indexRelation->rd_rel->relpages;
  166.     indexCatalogInfo[2] = indexRelation->rd_rel->reltuples;
  167.     RelationCloseHeapRelation(indexRelation);
  168.     
  169.     /* 
  170.      * Find the index ordering keys 
  171.      *
  172.      * Must use indclass to know when to stop looking since with
  173.      * functional indices there could be several keys (args) for
  174.      * one opclass. -mer 27 Sept 1991
  175.      */
  176.     for (i = 0; i < 8 && index->indclass[i]; ++i) {        /* 11-18 */
  177.         amopTuple = SearchSysCacheTuple(AMOPSTRATEGY,
  178.                         (char *) relam,
  179.                         (char *) index->indclass[i],
  180.                         (char *) amstrategy,
  181.                         (char *) NULL);
  182.         if (!HeapTupleIsValid(amopTuple))
  183.             elog(WARN, "IndexCatalogInformation: no amop %d %d %d",
  184.                  relam, index->indclass[i], amstrategy);
  185.         indexCatalogInfo[i+11] = ((AccessMethodOperatorTupleForm)
  186.             GETSTRUCT(amopTuple))->amopoprid;
  187.     }
  188.     return(1);
  189. }
  190.  
  191. /*
  192.  *    execIndexCatalogInformation
  193.  *
  194.  *    Returns the index relid for each index on the relation with OID 
  195.  *    'indrelid'.  'indexkeys' is loaded with the index key values.
  196.  */
  197. int32
  198. execIndexCatalogInformation(notFirst, indrelid, isarchival, indexkeys)
  199.     int32        notFirst;
  200.     ObjectId    indrelid;        /* indexED relation */
  201.     Boolean        isarchival;        /* XXX not used YET */
  202.     AttributeNumber    indexkeys[];
  203. {
  204.     register int    i;
  205.     int32        found, indexCatalogInfo[27];
  206.  
  207.     found = IndexCatalogInformation(notFirst, indrelid, isarchival,
  208.                     indexCatalogInfo);
  209.     if (! found || indexCatalogInfo[0] == 0)
  210.         return((int32) InvalidObjectId);
  211.     for (i = 0; i < MaxIndexAttributeNumber; ++i)
  212.         indexkeys[i] = indexCatalogInfo[i+3];
  213.     return((int32) indexCatalogInfo[0]);    
  214. }
  215.  
  216. /*
  217.  *    IndexSelectivity
  218.  *
  219.  *    Retrieves the 'amopnpages' and 'amopselect' parameters for each
  220.  *    AM operator when a given index (specified by 'indexrelid') is used.
  221.  *    These two parameters are returned by copying them to into an array of
  222.  *    floats.
  223.  *
  224.  *    Assumption: the attribute numbers and operator ObjectIds are in order
  225.  *    WRT to each other (otherwise, you have no way of knowing which
  226.  *    AM operator class or attribute number corresponds to which operator.
  227.  *
  228.  *    'varAttributeNumbers' contains attribute numbers for variables
  229.  *    'constValues' contains the constant values
  230.  *    'constFlags' describes how to treat the constants in each clause
  231.  *    'nIndexKeys' describes how many keys the index actually has
  232.  *
  233.  *    Returns 'selectivityInfo' filled with the sum of all pages touched
  234.  *    and the product of each clause's selectivity.
  235.  */
  236. /*ARGSUSED*/
  237. void
  238. IndexSelectivity(indexrelid, indrelid, nIndexKeys,
  239.          AccessMethodOperatorClasses, operatorObjectIds,
  240.          varAttributeNumbers, constValues, constFlags,
  241.          selectivityInfo)
  242.     ObjectId    indexrelid;
  243.     ObjectId    indrelid;
  244.     int32        nIndexKeys;
  245.     ObjectId    AccessMethodOperatorClasses[];    /* XXX not used? */
  246.     ObjectId    operatorObjectIds[];
  247.     int32        varAttributeNumbers[];
  248.     char        *constValues[];
  249.     int32        constFlags[];
  250.     float32data    selectivityInfo[];
  251. {
  252.     register    i, n;
  253.     HeapTuple    indexTuple, amopTuple;
  254.     IndexTupleForm    index;
  255.     AccessMethodOperatorTupleForm    amop;
  256.     ObjectId    indclass;
  257.     float64data    npages, select;
  258.     float64        amopnpages, amopselect;
  259.  
  260.     indexTuple = SearchSysCacheTuple(INDEXRELID,
  261.                      (char *) indexrelid, (char *) NULL,
  262.                      (char *) NULL, (char *) NULL);
  263.     if (!HeapTupleIsValid(indexTuple))
  264.         elog(WARN, "IndexSelectivity: index %d not found",
  265.              indexrelid);
  266.     index = (IndexTupleForm)GETSTRUCT(indexTuple);
  267.  
  268.     npages = 0.0;
  269.     select = 1.0;
  270.     for (n = 0; n < nIndexKeys; ++n) {
  271.         /* 
  272.          * Find the AM class for this key. 
  273.          *
  274.          * If the first attribute number is invalid then we have a
  275.          * functional index, and AM class is the first one defined
  276.          * since functional indices have exactly one key.
  277.          */
  278.         indclass = (varAttributeNumbers[0] == InvalidAttributeNumber) ?
  279.             index->indclass[0] : InvalidObjectId;
  280.         i = 0;
  281.         while ((i < nIndexKeys) && (indclass == InvalidObjectId)) {
  282.             if (varAttributeNumbers[n] == index->indkey[i]) {
  283.                 indclass = index->indclass[i];
  284.                 break;
  285.             }
  286.             i++;
  287.         }
  288.         if (!ObjectIdIsValid(indclass)) {
  289.             /*
  290.              * Presumably this means that we are using a functional
  291.              * index clause and so had no variable to match to
  292.              * the index key ... if not we are in trouble.
  293.              */
  294.             elog(NOTICE, "IndexSelectivity: no key %d in index %d",
  295.                  varAttributeNumbers[n], indexrelid);
  296.             continue;
  297.         }
  298.  
  299.         amopTuple = SearchSysCacheTuple(AMOPOPID,
  300.                         (char *) indclass,
  301.                         (char *) operatorObjectIds[n],
  302.                         (char *) NULL, (char *) NULL);
  303.         if (!HeapTupleIsValid(amopTuple))
  304.             elog(WARN, "IndexSelectivity: no amop %d %d",
  305.                  indclass, operatorObjectIds[n]);
  306.         amop = (AccessMethodOperatorTupleForm)GETSTRUCT(amopTuple);
  307.         amopnpages = (float64) fmgr(amop->amopnpages,
  308.                         (char *) operatorObjectIds[n],
  309.                         (char *) indrelid,
  310.                         (char *) varAttributeNumbers[n],
  311.                         (char *) constValues[n],
  312.                         (char *) constFlags[n],
  313.                         (char *) nIndexKeys, 
  314.                         (char *) indexrelid);
  315.         npages += PointerIsValid(amopnpages) ? *amopnpages : 0.0;
  316.         if ((i = npages) < npages)    /* ceil(npages)? */
  317.             npages += 1.0;
  318.         amopselect = (float64) fmgr(amop->amopselect,
  319.                         (char *) operatorObjectIds[n],
  320.                         (char *) indrelid,
  321.                         (char *) varAttributeNumbers[n],
  322.                         (char *) constValues[n],
  323.                         (char *) constFlags[n],
  324.                         (char *) nIndexKeys,
  325.                         (char *) indexrelid);
  326.         select *= PointerIsValid(amopselect) ? *amopselect : 1.0;
  327.     }
  328.     selectivityInfo[0] = npages;
  329.     selectivityInfo[1] = select;
  330. }
  331.  
  332. /*
  333.  *      restriction_selectivity in lisp system.
  334.  *    NOTE:  used to be called RestrictionClauseSelectivity in C
  335.  *
  336.  *    Returns the selectivity of a specified operator.
  337.  *    This code executes registered procedures stored in the
  338.  *    operator relation, by calling the function manager.
  339.  *
  340.  *    XXX The assumption in the selectivity procedures is that if the
  341.  *        relation OIDs or attribute numbers are -1, then the clause
  342.  *        isn't of the form (op var const).
  343.  */
  344. float64data
  345. restriction_selectivity(functionObjectId, operatorObjectId,
  346.             relationObjectId, attributeNumber,
  347.             constValue, constFlag)
  348.     ObjectId    functionObjectId;
  349.     ObjectId    operatorObjectId;
  350.     ObjectId    relationObjectId;
  351.     AttributeNumber    attributeNumber;
  352.     char        *constValue;
  353.     int32        constFlag;
  354. {
  355.     float64    result;
  356.  
  357.     result = (float64) fmgr(functionObjectId,
  358.                 (char *) operatorObjectId,
  359.                 (char *) relationObjectId, 
  360.                 (char *) attributeNumber,
  361.                 (char *) constValue,
  362.                 (char *) constFlag);
  363.     if (!PointerIsValid(result))
  364.         elog(WARN, "RestrictionClauseSelectivity: bad pointer");
  365.     if (*result < 0.0 || *result > 1.0)
  366.         elog(WARN, "RestrictionClauseSelectivity: bad value %lf",
  367.              *result);
  368.     return(*result);
  369. }
  370.  
  371. /*
  372.  *      join_selectivity in lisp system.
  373.  *    used to be called JoinClauseSelectivity in C
  374.  *
  375.  *    Returns the selectivity of a join operator.
  376.  *
  377.  *    XXX The assumption in the selectivity procedures is that if the
  378.  *        relation OIDs or attribute numbers are -1, then the clause
  379.  *        isn't of the form (op var var).
  380.  */
  381. float64data
  382. join_selectivity (functionObjectId, operatorObjectId,
  383.           relationObjectId1, attributeNumber1,
  384.           relationObjectId2, attributeNumber2)
  385.      ObjectId    functionObjectId;
  386.      ObjectId    operatorObjectId;
  387.      ObjectId    relationObjectId1;
  388.      AttributeNumber    attributeNumber1;
  389.      ObjectId     relationObjectId2;
  390.      AttributeNumber    attributeNumber2;
  391. {
  392.     float64    result = 0;
  393.     
  394.     result = (float64) fmgr(functionObjectId,
  395.                 (char *) operatorObjectId,
  396.                 (char *) relationObjectId1,
  397.                 (char *) attributeNumber1,
  398.                 (char *) relationObjectId2,
  399.                 (char *) attributeNumber2);
  400.     if (!PointerIsValid(result))
  401.       elog(WARN, "JoinClauseSelectivity: bad pointer");
  402.     if (*result < 0.0 || *result > 1.0)
  403.       elog(WARN, "JoinClauseSelectivity: bad value %lf",
  404.        *result);
  405.     return(*result);
  406. }
  407.  
  408. /*
  409.  *    find_all_inheritors
  410.  *
  411.  *    Returns a LISP list containing the OIDs of all relations which
  412.  *    inherits from the relation with OID 'inhparent'.
  413.  */
  414. LispValue
  415. find_inheritance_children (inhparent)
  416.      LispValue    inhparent;
  417. {
  418.     HeapTuple        inheritsTuple;
  419.     static ScanKeyEntryData    key[1] = {
  420.         { 0, InheritsParentAttributeNumber, F_OIDEQ }
  421.     };
  422.     Relation        relation;
  423.     HeapScanDesc        scan;
  424.     LispValue        lp = LispNil;
  425.     LispValue        list = LispNil;
  426.  
  427.     fmgr_info(F_OIDEQ, &key[0].func, &key[0].nargs);
  428.  
  429.     key[0].argument = ObjectIdGetDatum((ObjectId) LISPVALUE_INTEGER(inhparent));
  430.     relation = RelationNameOpenHeapRelation(InheritsRelationName);
  431.     scan = RelationBeginHeapScan(relation, 0, NowTimeQual,
  432.                      1, (ScanKey) key);
  433.     while (HeapTupleIsValid(inheritsTuple =
  434.                 HeapScanGetNextTuple(scan, 0,
  435.                              (Buffer *) NULL))) {
  436.          lp = lispInteger(((InheritsTupleForm)
  437.                    GETSTRUCT(inheritsTuple))->inhrel);
  438.          list = nappend1(list,lp);
  439.     }
  440.     HeapScanEnd(scan);
  441.     RelationCloseHeapRelation(relation);
  442.     return(list);
  443.    }
  444.  
  445. /*
  446.  *    VersionGetParents
  447.  *
  448.  *    Returns a LISP list containing the OIDs of all relations which are
  449.  *    base relations of the relation with OID 'verrelid'.
  450.  */
  451. LispValue
  452. VersionGetParents(verrelid, list)
  453.     LispValue    verrelid, list;
  454. {
  455.     HeapTuple        versionTuple;
  456.     static ScanKeyEntryData    key[1] = {
  457.         { 0, VersionRelationIdAttributeNumber, F_OIDEQ }
  458.     };
  459.     Relation        relation;
  460.     HeapScanDesc        scan;
  461.     LispValue        lp;
  462.     ObjectId        verbaseid;
  463.  
  464.     fmgr_info(F_OIDEQ, &key[0].func, &key[0].nargs);
  465.     relation = RelationNameOpenHeapRelation(VersionRelationName);
  466.     key[0].argument = ObjectIdGetDatum((ObjectId) LISPVALUE_INTEGER(verrelid));
  467.     scan = RelationBeginHeapScan(relation, 0, NowTimeQual,
  468.                      1, (ScanKey) key);
  469.     for (;;) {
  470.         versionTuple = HeapScanGetNextTuple(scan, 0,
  471.                             (Buffer *) NULL);
  472.         if (!HeapTupleIsValid(versionTuple))
  473.             break;
  474.         verbaseid = ((VersionTupleForm)
  475.                  GETSTRUCT(versionTuple))->verbaseid;
  476.         lp = lispList();
  477.         CAR(lp) = lispInteger(verbaseid);
  478.         CDR(lp) = CAR(list);
  479.         CAR(list) = lp;
  480.         key[0].argument = ObjectIdGetDatum(verbaseid);
  481.         HeapScanRestart(scan, 0, (ScanKey) key);
  482.     }
  483.     HeapScanEnd(scan);
  484.     RelationCloseHeapRelation(relation);
  485.     return(list);
  486. }
  487.