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

  1. /* ----------------------------------------------------------------
  2.  * testrtree.c --
  3.  *    B-tree test code.
  4.  * ----------------------------------------------------------------
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include "postgres.h"
  9.  
  10. #include "fmgr.h"    /* for M_STATIC/M_DYNAMIC */
  11.  
  12. #include "skey.h"
  13. #include "amutil.h"
  14.  
  15. #include "attnum.h"
  16. #include "attval.h"
  17. #include "bufmgr.h"
  18. #include "catname.h"
  19. #include "datum.h"
  20. #include "log.h"
  21. #include "genam.h"
  22. #include "heapam.h"
  23. #include "itemptr.h"
  24. #include "istrat.h"
  25. #include "itup.h"
  26. #include "name.h"
  27. /* #include "oid.h"  -- now in postgres.h */
  28. #include "portal.h"
  29. #include "sdir.h"
  30. #include "tqual.h"
  31. #include "valid.h"
  32. #include "xcxt.h"
  33.  
  34. #include "rtrees.h"
  35. #include "btree.h"
  36.  
  37. RcsId("$Header: /private/postgres/src/test/RCS/testrtree.c,v 1.12 1992/03/04 14:10:54 hong Exp $");
  38.  
  39. /* ----------------
  40.  *    constants
  41.  * ----------------
  42.  */
  43.  
  44. #define UninitializedQualification    0
  45. #define SingleQualification        1
  46. #define DoubleQualification        2
  47. #define MarkedQualification        3
  48.  
  49. #define MarkedTuplesToProcess        64
  50.  
  51. static int        QualificationState;
  52. ScanKeyEntryData    QualificationKeyData[2];
  53.  
  54. AttributeNumber        indexAttrNumber;
  55. ObjectId         indexAttrClass;
  56.  
  57. /* ----------------------------------------------------------------
  58.  *               misc functions
  59.  * ----------------------------------------------------------------
  60.  */
  61.  
  62. /* ----------------
  63.  *    DoCreateIndex
  64.  * ----------------
  65.  */
  66.  
  67. void 
  68. DoCreateIndex(heapName, indexName, attribute, cls)
  69.    Name            heapName;
  70.    Name            indexName;
  71.    AttributeNumber    attribute;
  72.    ObjectId        cls;
  73. {
  74.    AttributeNumber  attributeNumber[1];
  75.    ObjectId        attributeClass[1];
  76.  
  77.    elog(NOTICE, "DoCreateIndex... start");
  78.  
  79.    attributeNumber[0] = attribute;
  80.    attributeClass[0] =  cls;
  81.  
  82.  
  83.     RelationNameCreateIndexRelation(heapName,
  84.                            indexName,
  85.                         402,    /* rtree am number */
  86.                         1,
  87.                         attributeNumber,
  88.                         attributeClass,
  89.                         0,
  90.                         (Datum *) NULL);
  91.  
  92.    elog(NOTICE, "DoCreateIndex... end");
  93.  
  94. }
  95.  
  96. /* ----------------
  97.  *    ShowResult
  98.  * ----------------
  99.  */
  100.  
  101. void 
  102. ShowResult(result, heapRelation)
  103.    GeneralRetrieveIndexResult    result;
  104.    Relation            heapRelation;
  105. {
  106.    ItemPointer    pointer;
  107.  
  108.    Assert(GeneralRetrieveIndexResultIsValid(result));
  109.  
  110.    pointer = GeneralRetrieveIndexResultGetHeapItemPointer(result);
  111.  
  112.    printf("\t");
  113.  
  114.    if (!ItemPointerIsValid(pointer)) {
  115.       printf("<invalid>\n");
  116.    } else {
  117.       HeapTuple    tuple;
  118.       Buffer    buffer;
  119.  
  120.       printf("[b,p,o %d, %d, %3d] ",
  121.          ItemPointerGetBlockNumber(pointer),
  122.          ItemPointerSimpleGetPageNumber(pointer),
  123.          ItemPointerSimpleGetOffsetNumber(pointer));
  124.  
  125.       tuple =
  126.      RelationGetHeapTupleByItemPointer(heapRelation,
  127.             NowTimeQual,
  128.                        pointer,
  129.                        &buffer);
  130.  
  131.       if (!HeapTupleIsValid(tuple)) {
  132.      printf("*NULL*\n");
  133.  
  134.       } else {
  135.      TupleDescriptor    descriptor;
  136.      AttributeValue        value;
  137.      Boolean        valueIsNull;
  138.  
  139.      descriptor = RelationGetTupleDescriptor(heapRelation);
  140.  
  141.      /* We might want to print more than just the index att, here */
  142.      value =
  143.         HeapTupleGetAttributeValue(tuple,
  144.                        buffer,
  145.                        indexAttrNumber,
  146.                        descriptor,
  147.                        &valueIsNull);
  148.  
  149.      if (valueIsNull) {
  150.         printf("<NULL>\n");
  151.      } else {
  152.         printf("<0x%x(%d)>\n",
  153.            DatumGetObjectId(value), 
  154.            DatumGetObjectId(value));
  155.      }
  156.  
  157.      ReleaseBuffer(buffer);
  158.       }
  159.    }
  160. }
  161.  
  162. /* ----------------
  163.  *    ShowScanKeyEntry
  164.  * ----------------
  165.  */
  166.  
  167. void 
  168. ShowScanKeyEntry(entry)
  169.    ScanKeyEntry    entry;
  170. {
  171.    printf("Qualification is procedure 0x%x(%d) for %d with 0x%x\n",
  172.       entry->procedure,
  173.       entry->procedure,
  174.       DatumGetObjectId(entry->argument),
  175.       entry->flags);
  176. }
  177.  
  178. /* ----------------------------------------------------------------
  179.  *              scan functions
  180.  * ----------------------------------------------------------------
  181.  */
  182.  
  183. /* ----------------
  184.  *    DoForwardScan
  185.  * ----------------
  186.  */
  187.  
  188. void 
  189. DoForwardScan(indexRelation, heapRelation)
  190.    Relation    indexRelation;
  191.    Relation    heapRelation;
  192. {
  193.    IndexScanDesc        scan;
  194.    GeneralRetrieveIndexResult    result;
  195.  
  196.    puts("A complete forward scan of the index reveals...");
  197.  
  198.    scan = RelationGetIndexScan(indexRelation, 0, 0, (ScanKey) NULL);
  199.  
  200.    for (;;) {
  201.       result = AMgettuple(scan, 1);
  202.  
  203.       if (!GeneralRetrieveIndexResultIsValid(result))
  204.      break;
  205.  
  206.      ShowResult(result, heapRelation);
  207.    }
  208.  
  209.    AMendscan(scan);
  210. }
  211.  
  212. /* ----------------
  213.  *    DoBackwardScan
  214.  * ----------------
  215.  */
  216.  
  217. void 
  218. DoBackwardScan(indexRelation, heapRelation)
  219.    Relation    indexRelation;
  220.    Relation    heapRelation;
  221. {
  222.    IndexScanDesc        scan;
  223.    GeneralRetrieveIndexResult    result;
  224.  
  225.    puts("A complete reverse scan of the index reveals...");
  226.  
  227.    scan = RelationGetIndexScan(indexRelation, -1, 0, (ScanKey) NULL);
  228.  
  229.    for (;;) {
  230.       result = AMgettuple(scan, -1);
  231.  
  232.       if (!GeneralRetrieveIndexResultIsValid(result))
  233.      break;
  234.  
  235.      ShowResult(result, heapRelation);
  236.    }
  237.  
  238.    AMendscan(scan);
  239. }
  240.  
  241.  
  242. /* ----------------
  243.  *    DoSingleQualification
  244.  * ----------------
  245.  */
  246.  
  247. void 
  248. DoSingleQualification(indexRelation, heapRelation, entry)
  249.    Relation    indexRelation;
  250.    Relation    heapRelation;
  251.    ScanKeyEntry    entry;
  252. {
  253.    IndexScanDesc        scan;
  254.    GeneralRetrieveIndexResult    result;
  255.  
  256.    QualificationKeyData[0] = *entry;
  257.  
  258.    ShowScanKeyEntry(&QualificationKeyData[0]);
  259.    puts("A scan of the index reveals...");
  260.  
  261.    scan = RelationGetIndexScan(indexRelation, 0, 1,
  262.                    (ScanKey)QualificationKeyData);
  263.  
  264.    for (;;) {
  265.       result = AMgettuple(scan, 1);
  266.  
  267.       if (!GeneralRetrieveIndexResultIsValid(result))
  268.      break;
  269.  
  270.      ShowResult(result, heapRelation);
  271.    }
  272.  
  273.    AMendscan(scan);
  274. }
  275.  
  276.  
  277. /* ----------------
  278.  *    DoDoubleQualification
  279.  * ----------------
  280.  */
  281.  
  282. void 
  283. DoDoubleQualification(indexRelation, heapRelation, entry)
  284.    Relation    indexRelation;
  285.    Relation    heapRelation;
  286.    ScanKeyEntry    entry;
  287. {
  288.    IndexScanDesc        scan;
  289.    GeneralRetrieveIndexResult    result;
  290.  
  291.    QualificationKeyData[1] = *entry;
  292.  
  293.    ShowScanKeyEntry(&QualificationKeyData[0]);
  294.    ShowScanKeyEntry(&QualificationKeyData[1]);
  295.    puts("A scan of the index reveals...");
  296.  
  297.    scan = RelationGetIndexScan(indexRelation, 0, 2,
  298.                    (ScanKey)QualificationKeyData);
  299.    for (;;) {
  300.       result = AMgettuple(scan, 1);
  301.  
  302.       if (!GeneralRetrieveIndexResultIsValid(result))
  303.      break;
  304.  
  305.      ShowResult(result, heapRelation);
  306.    }
  307.    AMendscan(scan);
  308. }
  309.  
  310. /* ----------------
  311.  *    DoMarkedQualification
  312.  * ----------------
  313.  */
  314.  
  315. void
  316. DoMarkedQualification(indexRelation, heapRelation, entry)
  317.    Relation    indexRelation;
  318.    Relation    heapRelation;
  319.    ScanKeyEntry    entry;
  320. {
  321.    IndexScanDesc        scan;
  322.    GeneralRetrieveIndexResult    result;
  323.    int                tuplesLeft;
  324.    bool                markIsSet;
  325.    int                whichWay;
  326.  
  327.    tuplesLeft = MarkedTuplesToProcess;
  328.    markIsSet = false;
  329.  
  330.    srandom((int)time(0));
  331.  
  332.    QualificationKeyData[0] = *entry;
  333.  
  334.    ShowScanKeyEntry(&QualificationKeyData[0]);
  335.    puts("A scan of the index reveals...");
  336.  
  337.    scan = RelationGetIndexScan(indexRelation, (bool) (0x1 & random()), 1,
  338.                    (ScanKey)QualificationKeyData);
  339.  
  340.    while (tuplesLeft > 0) {
  341.       if (!(random() & 0xf)) {
  342.      printf("RESTARTING SCAN\n");
  343.      AMrescan(scan, (bool) (0x1 & random()), (ScanKey)QualificationKeyData);
  344.      markIsSet = false;
  345.       }
  346.       if (!(random() & 0x3)) {
  347.      if (markIsSet) {
  348.         printf("RESTORING MARK\n");
  349.         AMrestrpos(scan);
  350.         if (!(0x1 & random())) {
  351.            markIsSet = false;
  352.         }
  353.      } else {
  354.         printf("SET MARK\n");
  355.         AMmarkpos(scan);
  356.         markIsSet = true;
  357.      }
  358.       }
  359.  
  360.       if ((random() & 0x1) == 0x1)
  361.      whichWay = -1;        /* backward */
  362.       else
  363.      whichWay = 1;        /* forward */
  364.  
  365.       result = AMgettuple(scan, whichWay);
  366.  
  367.       if (!GeneralRetrieveIndexResultIsValid(result)) {
  368.      puts("\t*NULL*");
  369.       } else {
  370.      ShowResult(result, heapRelation);
  371.       }
  372.  
  373.       tuplesLeft -= 1;
  374.    }
  375.    AMendscan(scan);
  376. }
  377.  
  378. /* ----------------------------------------------------------------
  379.  *    DoQualifiedScan
  380.  * ----------------------------------------------------------------
  381.  */
  382.  
  383. void
  384. DoQualifiedScan(indexRelation, heapRelation, operation, flags, returnType)
  385.    Relation    indexRelation;
  386.    Relation    heapRelation;
  387.    char        *operation;
  388.    uint16    flags;
  389.    ObjectId    returnType;
  390. {
  391.    StrategyNumber    strategyNumber;
  392.    IndexStrategy    indexStrategy;
  393.    StrategyMap        strategyMap;
  394.    ScanKeyEntry        scanKeyEntry;
  395.  
  396.    if (strcmp(operation, "<") == 0) {    
  397.       strategyNumber = BTreeLessThanStrategyNumber;
  398.    } else if (strcmp(operation, "<=") == 0) {
  399.       strategyNumber = BTreeLessThanOrEqualStrategyNumber;
  400.    } else if (strcmp(operation, "=") == 0) {
  401.       strategyNumber = BTreeEqualStrategyNumber;
  402.    } else if (strcmp(operation, ">=") == 0) {
  403.       strategyNumber = BTreeGreaterThanOrEqualStrategyNumber;
  404.    } else if (strcmp(operation, ">") == 0) {
  405.       strategyNumber = BTreeGreaterThanStrategyNumber;
  406.    } else {
  407.       fprintf(stderr, "testrtree: unknown operation \"%s\"\n",
  408.           operation);
  409.       return;
  410.    }
  411.  
  412.    indexStrategy = RelationGetIndexStrategy(indexRelation);
  413.  
  414.    strategyMap = IndexStrategyGetStrategyMap(indexStrategy,
  415.                          BTreeNumberOfStrategies, 1);
  416.  
  417.    scanKeyEntry = StrategyMapGetScanKeyEntry(strategyMap, strategyNumber);
  418.  
  419.    if (!RegProcedureIsValid(scanKeyEntry->procedure)) {
  420.       fprintf(stderr, "testrtree: no procedure for strategy %d\n",
  421.           strategyNumber);
  422.  
  423.       return;
  424.    }
  425.  
  426.    /*
  427.     * Note: very dangerous to modify the reldesc, since it is cached.
  428.     */
  429.    scanKeyEntry->attributeNumber = 1;
  430.    scanKeyEntry->flags = flags;
  431.    scanKeyEntry->argument = ObjectIdGetDatum(returnType);
  432.  
  433.    switch (QualificationState) {
  434.    case UninitializedQualification:
  435.    case MarkedQualification:
  436.       QualificationState = SingleQualification;
  437.       DoSingleQualification(indexRelation, heapRelation,
  438.                 scanKeyEntry);
  439.       break;
  440.    case SingleQualification:
  441.       QualificationState = DoubleQualification;
  442.       DoDoubleQualification(indexRelation, heapRelation,
  443.                 scanKeyEntry);
  444.       break;
  445.    case DoubleQualification:
  446.       QualificationState = MarkedQualification;
  447.       DoMarkedQualification(indexRelation, heapRelation,
  448.                 scanKeyEntry);
  449.       break;
  450.    default:
  451.       fprintf(stderr, "testrtree: internal error!");
  452.       exitpg(255);
  453.    }
  454. }
  455.  
  456. /* ----------------------------------------------------------------
  457.  *                 TestMain
  458.  * ----------------------------------------------------------------
  459.  */
  460.  
  461. void
  462. TestMain()
  463. {
  464.    static NameData    heapNameData;
  465.    static NameData     indexNameData;
  466.           Relation    indexRelation;
  467.           Relation    heapRelation;
  468.    static int            beenHere = 0;
  469.       Portal    portal;
  470.  
  471.  
  472.    Relation        AMopenr();    /* XXX */
  473.  
  474.  
  475.    /*
  476.     *  Create a dummy portal to get memory management.
  477.     */
  478.  
  479.    portal = CreatePortal("<blank>");
  480.    StartTransactionCommand(portal);
  481.  
  482.    if (beenHere == 0) {
  483.       char *result;
  484.       bool newIndex;
  485.       bool done;
  486.  
  487.       /* discard any stuff on the input stream */
  488.       fseek(stdin, 0, 2);
  489.  
  490.       fprintf(stdout, "Relation: ");
  491.       fflush(stdout);
  492.  
  493.       if ((result = gets(&heapNameData.data[0])) == (char *) NULL) {
  494.      elog(NOTICE, "testrtree: no heap specified");
  495.      exitpg(0);
  496.       }
  497.  
  498.       fprintf(stdout, "Index name: ");
  499.       fflush(stdout);
  500.  
  501.       if ((result = gets(&indexNameData.data[0])) == (char *) NULL) {
  502.      elog(NOTICE, "testrtree: no index specified");
  503.      exitpg(0);
  504.       }
  505.  
  506.       do {
  507.      char buf[20];
  508.  
  509.      fprintf(stdout, "Is this a new index? (y/n) ");
  510.      fflush(stdout);
  511.  
  512.      result = gets(&buf[0]);
  513.  
  514.      if (result != (char *) NULL) {
  515.         if (strcmp(result, "y") == 0) {
  516.            newIndex = true;
  517.            done = true;
  518.         } else if (strcmp(result, "n") == 0) {
  519.            newIndex = false;
  520.            done = true;
  521.         } else {
  522.            fprintf(stdout, "*** y or n only ***\n");
  523.            done = false;
  524.         }
  525.      } else {
  526.         fprintf(stdout, "*** y or n only ***\n");
  527.         done = false;
  528.      }
  529.       } while (!done);
  530.  
  531.       fprintf(stdout, "Attribute number for index: ");
  532.       fflush(stdout);
  533.  
  534.       if (scanf("%hd", &indexAttrNumber) != 1) {
  535.      elog(NOTICE, "testrtree: attribute incorrectly specified");
  536.      exitpg(0);
  537.       }
  538.  
  539.       if (newIndex) {
  540.      fprintf(stdout, "Assuming box attribute.\n");
  541.      indexAttrClass = 422;
  542.  
  543.      fseek(stdin, 0, 2);
  544.  
  545.      beenHere = 1;
  546.  
  547.      DoCreateIndex(&heapNameData, &indexNameData,
  548.             indexAttrNumber, indexAttrClass);
  549.       }
  550.  
  551.       CommitTransactionCommand();
  552.       StartTransactionCommand(portal);
  553.  
  554.       beenHere = 2;
  555.    } else if (beenHere == 1) {
  556.       elog(NOTICE, "testrtree: %s relation may exist--continuing!",
  557.        indexNameData.data);
  558.       beenHere = 2;
  559.  
  560.    } else if (beenHere > 1) {
  561.       elog(FATAL, "testrtree: giving up!");
  562.    }
  563.  
  564.    indexRelation = AMopenr(indexNameData.data);    /* XXX */
  565.    printf("And the relation is...\n");
  566.    fflush(stdout);
  567.    rtshowtree(indexRelation);
  568.  
  569. #ifdef NOTYET
  570.  
  571.    DoForwardScan(indexRelation, heapRelation);
  572.  
  573.    DoBackwardScan(indexRelation, heapRelation);
  574.  
  575.    for (;;) {
  576.       int        status;
  577.       NameData        operatorNameData;
  578.       ObjectId        returnType;
  579.  
  580.       puts("\nPlease enter an operator and an integer value");
  581.  
  582.       fseek(stdin, 0, 2);    /* discard any stuff on the input stream */
  583.       status = scanf("%s%d", &(operatorNameData), &returnType);
  584.  
  585.       if (status <= 0) {
  586.      break;
  587.       } else if (status != 2) {
  588.      elog(NOTICE, "testrtree: improper qualification specified");
  589.      exitpg(0);
  590.       }
  591.  
  592.       DoQualifiedScan(indexRelation, heapRelation, &operatorNameData,
  593.               0, returnType);
  594.    }
  595.  
  596.    RelationCloseHeapRelation(heapRelation);
  597.    RelationCloseIndexRelation(indexRelation);
  598.  
  599.    puts("\nDone!");
  600.    CommitTransactionCommand();
  601.  
  602. #endif NOTYET
  603.  
  604. }
  605.