home *** CD-ROM | disk | FTP | other *** search
- /* ----------------------------------------------------------------
- * testbtree.c --
- * B-tree test code.
- * ----------------------------------------------------------------
- */
-
- #include "fmgr.h" /* for M_STATIC/M_DYNAMIC */
-
- #include <stdio.h>
-
- #include "c.h"
-
- #include "attnum.h"
- #include "attval.h"
- #include "bufmgr.h"
- #include "catname.h"
- #include "datum.h"
- #include "log.h"
- #include "genam.h"
- #include "heapam.h"
- #include "itemptr.h"
- #include "istrat.h"
- #include "itup.h"
- #include "name.h"
- #include "oid.h"
- #include "portal.h"
- #include "sdir.h"
- #include "tqual.h"
- #include "valid.h"
- #include "xcxt.h"
-
- #include "btree.h"
-
- RcsId("$Header: /private/postgres/src/test/RCS/testbtree.c,v 1.16 1992/03/04 14:10:47 hong Exp $");
-
- /* ----------------
- * constants
- * ----------------
- */
-
- #define UninitializedQualification 0
- #define SingleQualification 1
- #define DoubleQualification 2
- #define MarkedQualification 3
-
- #define MarkedTuplesToProcess 64
-
- static int QualificationState;
- ScanKeyEntryData QualificationKeyData[2];
-
- AttributeNumber indexAttrNumber;
- ObjectId indexAttrClass;
-
- /* ----------------------------------------------------------------
- * misc functions
- * ----------------------------------------------------------------
- */
-
- /* ----------------
- * DoCreateIndex
- * ----------------
- */
-
- void FUNCTION
- DoCreateIndex(heapName, indexName, attribute, cls)
- Name heapName;
- Name indexName;
- AttributeNumber attribute;
- ObjectId cls;
- {
- AttributeNumber attributeNumber[1];
- ObjectId attributeClass[1];
-
- elog(NOTICE, "DoCreateIndex... start");
-
- attributeNumber[0] = attribute;
- attributeClass[0] = cls;
-
- RelationNameCreateIndexRelation(heapName,
- indexName,
- 400 /* B-tree AM */,
- 1,
- attributeNumber,
- attributeClass,
- 0,
- (Datum *) NULL);
- fflush(stdout);
- fflush(stderr);
- elog(NOTICE, "DoCreateIndex... end");
-
- }
-
- /* ----------------
- * ShowResult
- * ----------------
- */
-
- void FUNCTION
- ShowResult(result, heapRelation)
- GeneralRetrieveIndexResult result;
- Relation heapRelation;
- {
- ItemPointer pointer;
-
- Assert(GeneralRetrieveIndexResultIsValid(result));
-
- pointer = GeneralRetrieveIndexResultGetHeapItemPointer(result);
-
- printf("\t");
-
- if (!ItemPointerIsValid(pointer)) {
- printf("<invalid>\n");
- } else {
- HeapTuple tuple;
- Buffer buffer;
-
- printf("[b,p,o %d, %d, %3d] ",
- ItemPointerGetBlockNumber(pointer),
- ItemPointerSimpleGetPageNumber(pointer),
- ItemPointerSimpleGetOffsetNumber(pointer));
-
- tuple =
- RelationGetHeapTupleByItemPointer(heapRelation,
- NowTimeQual,
- pointer,
- &buffer);
-
- if (!HeapTupleIsValid(tuple)) {
- printf("*NULL*\n");
-
- } else {
- TupleDescriptor descriptor;
- AttributeValue value;
- Boolean valueIsNull;
-
- descriptor = RelationGetTupleDescriptor(heapRelation);
-
- /* We might want to print more than just the index att, here */
- value =
- HeapTupleGetAttributeValue(tuple,
- buffer,
- indexAttrNumber,
- descriptor,
- &valueIsNull);
-
- if (valueIsNull) {
- printf("<NULL>\n");
- } else {
- printf("<0x%x(%d)>\n",
- DatumGetObjectId(value),
- DatumGetObjectId(value));
- }
-
- ReleaseBuffer(buffer);
- }
- }
- }
-
- /* ----------------
- * ShowScanKeyEntry
- * ----------------
- */
-
- void FUNCTION
- ShowScanKeyEntry(entry)
- ScanKeyEntry entry;
- {
- printf("Qualification is procedure 0x%x(%d) for %d with 0x%x\n",
- entry->procedure,
- entry->procedure,
- DatumGetObjectId(entry->argument),
- entry->flags);
- }
-
- /* ----------------------------------------------------------------
- * browse functions
- * ----------------------------------------------------------------
- */
-
- /* ----------------
- * DoBTreeBrowse
- * ----------------
- */
-
- /*ARGSUSED*/
- void FUNCTION
- DoBTreeBrowse(indexRelation, heapRelation)
- Relation indexRelation;
- Relation heapRelation;
- {
- BTreeNode node;
- BlockNumber blockNumber;
- PageNumber pageNumber;
- int cnt;
-
- puts("\n--- BTree Browse ---");
- puts("at the prompt, enter a block number and a page number");
- puts("separated by a space or \".\" alone to end\n");
-
- forever {
- Puts("browse> ");
- fflush(stdout);
-
- cnt = scanf("%ld %hd", &blockNumber, &pageNumber);
- if (cnt != 2) {
- puts("\n--- ending BTree Browse ---");
- fseek(stdin, 0, 2);
- break;
- }
-
- node = RelationFormBTreeNode(indexRelation, blockNumber, pageNumber);
- DumpBTreeNode(node);
- BTreeNodeFree(node);
- putchar('\n');
- }
- }
-
- /* ----------------------------------------------------------------
- * scan functions
- * ----------------------------------------------------------------
- */
-
- /* ----------------
- * DoForwardScan
- * ----------------
- */
-
- void FUNCTION
- DoForwardScan(indexRelation, heapRelation)
- Relation indexRelation;
- Relation heapRelation;
- {
- IndexScanDesc scan;
- GeneralRetrieveIndexResult result;
-
- puts("A complete forward scan of the index reveals...");
-
- scan = RelationGetIndexScan(indexRelation, 0, 0, (ScanKey) NULL);
-
- for (;;) {
- result = AMgettuple(scan, 1);
-
- if (!GeneralRetrieveIndexResultIsValid(result))
- break;
-
- ShowResult(result, heapRelation);
- }
-
- AMendscan(scan);
- }
-
- /* ----------------
- * DoBackwardScan
- * ----------------
- */
-
- void FUNCTION
- DoBackwardScan(indexRelation, heapRelation)
- Relation indexRelation;
- Relation heapRelation;
- {
- IndexScanDesc scan;
- GeneralRetrieveIndexResult result;
-
- puts("A complete reverse scan of the index reveals...");
-
- scan = RelationGetIndexScan(indexRelation, -1, 0, (ScanKey) NULL);
-
- for (;;) {
- result = AMgettuple(scan, -1);
-
- if (!GeneralRetrieveIndexResultIsValid(result))
- break;
-
- ShowResult(result, heapRelation);
- }
-
- AMendscan(scan);
- }
-
-
- /* ----------------
- * DoSingleQualification
- * ----------------
- */
-
- void FUNCTION
- DoSingleQualification(indexRelation, heapRelation, entry)
- Relation indexRelation;
- Relation heapRelation;
- ScanKeyEntry entry;
- {
- IndexScanDesc scan;
- GeneralRetrieveIndexResult result;
-
- QualificationKeyData[0] = *entry;
-
- ShowScanKeyEntry(&QualificationKeyData[0]);
- puts("A scan of the index with one qualification reveals...");
-
- scan = RelationGetIndexScan(indexRelation, 0, 1,
- (ScanKey)QualificationKeyData);
-
- for (;;) {
- result = AMgettuple(scan, 1);
-
- if (!GeneralRetrieveIndexResultIsValid(result))
- break;
-
- ShowResult(result, heapRelation);
- }
-
- AMendscan(scan);
- }
-
-
- /* ----------------
- * DoDoubleQualification
- * ----------------
- */
-
- void FUNCTION
- DoDoubleQualification(indexRelation, heapRelation, entry)
- Relation indexRelation;
- Relation heapRelation;
- ScanKeyEntry entry;
- {
- IndexScanDesc scan;
- GeneralRetrieveIndexResult result;
-
- QualificationKeyData[1] = *entry;
-
- ShowScanKeyEntry(&QualificationKeyData[0]);
- ShowScanKeyEntry(&QualificationKeyData[1]);
- puts("A scan of the index with two qualifications reveals...");
-
- scan = RelationGetIndexScan(indexRelation, 0, 2,
- (ScanKey)QualificationKeyData);
- for (;;) {
- result = AMgettuple(scan, 1);
-
- if (!GeneralRetrieveIndexResultIsValid(result))
- break;
-
- ShowResult(result, heapRelation);
- }
- AMendscan(scan);
- }
-
- /* ----------------
- * DoMarkedQualification
- * ----------------
- */
-
- void
- DoMarkedQualification(indexRelation, heapRelation, entry)
- Relation indexRelation;
- Relation heapRelation;
- ScanKeyEntry entry;
- {
- IndexScanDesc scan;
- GeneralRetrieveIndexResult result;
- int tuplesLeft;
- bool markIsSet;
- int whichWay;
-
- tuplesLeft = MarkedTuplesToProcess;
- markIsSet = false;
-
- srandom((int)time(0));
-
- QualificationKeyData[0] = *entry;
-
- ShowScanKeyEntry(&QualificationKeyData[0]);
- puts("A scan of the index reveals...");
-
- scan = RelationGetIndexScan(indexRelation, (bool) (0x1 & random()), 1,
- (ScanKey)QualificationKeyData);
-
- while (tuplesLeft > 0) {
- if (!(random() & 0xf)) {
- printf("RESTARTING SCAN\n");
- AMrescan(scan, (bool) (0x1 & random()), (ScanKey)QualificationKeyData);
- markIsSet = false;
- }
- if (!(random() & 0x3)) {
- if (markIsSet) {
- printf("RESTORING MARK\n");
- AMrestrpos(scan);
- if (!(0x1 & random())) {
- markIsSet = false;
- }
- } else {
- printf("SET MARK\n");
- AMmarkpos(scan);
- markIsSet = true;
- }
- }
-
- if ((random() & 0x1) == 0x1)
- whichWay = -1; /* backward */
- else
- whichWay = 1; /* forward */
-
- result = AMgettuple(scan, whichWay);
-
- if (!GeneralRetrieveIndexResultIsValid(result)) {
- puts("\t*NULL*");
- } else {
- ShowResult(result, heapRelation);
- }
-
- tuplesLeft -= 1;
- }
- AMendscan(scan);
- }
-
- /* ----------------------------------------------------------------
- * DoQualifiedScan
- * ----------------------------------------------------------------
- */
-
- void
- DoQualifiedScan(indexRelation, heapRelation, operation, flags, returnType)
- Relation indexRelation;
- Relation heapRelation;
- char *operation;
- uint16 flags;
- ObjectId returnType;
- {
- ScanKeyEntry scanKeyEntry;
- extern ScanKeyEntry GetScanKeyEntry();
-
- scanKeyEntry = GetScanKeyEntry(indexRelation, operation);
-
- /*
- * Note: very dangerous to modify the reldesc, since it is cached.
- */
- scanKeyEntry->attributeNumber = 1;
- scanKeyEntry->flags = flags;
- scanKeyEntry->argument = ObjectIdGetDatum(returnType);
-
- switch (QualificationState) {
- case UninitializedQualification:
- case MarkedQualification:
- QualificationState = SingleQualification;
- DoSingleQualification(indexRelation, heapRelation,
- scanKeyEntry);
- break;
- case SingleQualification:
- QualificationState = DoubleQualification;
- DoDoubleQualification(indexRelation, heapRelation,
- scanKeyEntry);
- break;
- case DoubleQualification:
- QualificationState = MarkedQualification;
- DoMarkedQualification(indexRelation, heapRelation,
- scanKeyEntry);
- break;
- default:
- fprintf(stderr, "testbtree: internal error!");
- exitpg(255);
- }
- }
-
- void
- DoRuleLockInsertion(indexRelation)
- Relation indexRelation;
- {
- BTreeSearchKey v_left, v_right;
- IndexTuple itup_left, itup_right;
- TupleDescriptor idesc;
- Datum datum[1];
- Boolean null[1];
- ScanKeyEntry skeyEntry;
- ScanKeyData myLeftScanKey[1];
- ScanKeyData myRightScanKey[1];
- BTreeInsertDataData id_left, id_right;
-
- idesc = RelationGetTupleDescriptor(indexRelation);
-
- id_left.type = BTREE_LEAF_INSERT_DATA | BTREE_RLOCK_L_INSERT_DATA;
- id_right.type = BTREE_LEAF_INSERT_DATA | BTREE_RLOCK_R_INSERT_DATA;
-
- for (;;) {
- char opname[10];
- int opkey;
-
- /* clear out the input stream */
- fseek(stdin, 0, 2);
-
- fprintf(stdout, "Enter left operator/key pair: ");
- fflush(stdout);
- if (scanf("%s%d", &opname[0], &opkey) != 2)
- break;
-
- datum[0] = Int32GetDatum(opkey);
- null[0] = ' ';
-
- itup_left = FormIndexTuple(1, idesc, datum, null);
- id_left.indexTuple = itup_left;
- id_left.size = psize(itup_left);
-
- skeyEntry = GetScanKeyEntry(indexRelation, opname);
- myLeftScanKey[0].data[0] = *skeyEntry;
- myLeftScanKey[0].data[0].attributeNumber = indexAttrNumber;
- myLeftScanKey[0].data[0].argument = Int32GetDatum(opkey);
-
- v_left = RelationFormBTreeSearchKey(indexRelation,
- &id_left,
- 1,
- &myLeftScanKey[0],
- NoMovementScanDirection,
- (ItemPointer) NULL);
-
- fprintf(stdout, "Enter right operator/key pair: ");
- fflush(stdout);
- scanf("%s%d", &opname[0], &opkey);
-
- datum[0] = Int32GetDatum(opkey);
- null[0] = ' ';
-
- itup_right = FormIndexTuple(1, idesc, datum, null);
- id_right.indexTuple = itup_right;
- id_right.size = psize(itup_right);
-
- skeyEntry = GetScanKeyEntry(indexRelation, opname);
- myRightScanKey[0].data[0] = *skeyEntry;
- myRightScanKey[0].data[0].attributeNumber = indexAttrNumber;
- myRightScanKey[0].data[0].argument = Int32GetDatum(opkey);
-
- v_right = RelationFormBTreeSearchKey(indexRelation,
- &id_right,
- 1,
- &myRightScanKey[0],
- NoMovementScanDirection,
- (ItemPointer) NULL);
-
- BTreeRuleLockInsert(v_left, v_right);
- }
- }
-
- ScanKeyEntry
- GetScanKeyEntry(indexRelation, operation)
- Relation indexRelation;
- char *operation;
- {
- StrategyNumber strategyNumber;
- IndexStrategy indexStrategy;
- StrategyMap strategyMap;
- ScanKeyEntry scanKeyEntry;
-
- if (strcmp(operation, "<") == 0) {
- strategyNumber = BTreeLessThanStrategyNumber;
- } else if (strcmp(operation, "<=") == 0) {
- strategyNumber = BTreeLessThanOrEqualStrategyNumber;
- } else if (strcmp(operation, "=") == 0) {
- strategyNumber = BTreeEqualStrategyNumber;
- } else if (strcmp(operation, ">=") == 0) {
- strategyNumber = BTreeGreaterThanOrEqualStrategyNumber;
- } else if (strcmp(operation, ">") == 0) {
- strategyNumber = BTreeGreaterThanStrategyNumber;
- } else {
- fprintf(stderr, "testbtree: unknown operation \"%s\"\n",
- operation);
- return ((ScanKeyEntry) NULL);
- }
-
- indexStrategy = RelationGetIndexStrategy(indexRelation);
- strategyMap = IndexStrategyGetStrategyMap(indexStrategy,
- BTreeNumberOfStrategies, 1);
- scanKeyEntry = StrategyMapGetScanKeyEntry(strategyMap, strategyNumber);
-
- if (!RegProcedureIsValid(scanKeyEntry->procedure)) {
- fprintf(stderr, "testbtree: no procedure for strategy %d\n",
- strategyNumber);
-
- return ((ScanKeyEntry) NULL);
- }
-
- return (scanKeyEntry);
- }
-
-
- /* ----------------------------------------------------------------
- * TestMain
- * ----------------------------------------------------------------
- */
-
- void FUNCTION
- TestMain()
- {
- static NameData heapNameData;
- static NameData indexNameData;
- Relation indexRelation;
- Relation heapRelation;
- static int beenHere = 0;
- Portal portal;
-
-
- Relation AMopenr(); /* XXX */
-
-
- portal = CreatePortal("<blank>");
- StartTransactionCommand(portal);
-
- if (beenHere == 0) {
- char *result;
- bool newIndex;
- bool done;
-
- /* discard any stuff on the input stream */
- fseek(stdin, 0, 2);
-
- fprintf(stdout, "Relation: ");
- fflush(stdout);
-
- if ((result = gets(&heapNameData.data[0])) == (char *) NULL) {
- elog(NOTICE, "testbtree: no heap specified");
- exitpg(0);
- }
-
- fprintf(stdout, "Index name: ");
- fflush(stdout);
-
- if ((result = gets(&indexNameData.data[0])) == (char *) NULL) {
- elog(NOTICE, "testbtree: no index specified");
- exitpg(0);
- }
-
- do {
- char buf[20];
-
- fprintf(stdout, "Is this a new index? (y/n) ");
- fflush(stdout);
-
- result = gets(&buf[0]);
-
- if (result != (char *) NULL) {
- if (strcmp(result, "y") == 0) {
- newIndex = true;
- done = true;
- } else if (strcmp(result, "n") == 0) {
- newIndex = false;
- done = true;
- } else {
- fprintf(stdout, "*** y or n only ***\n");
- done = false;
- }
- } else {
- fprintf(stdout, "*** y or n only ***\n");
- done = false;
- }
- } while (!done);
-
- fprintf(stdout, "Attribute number for index: ");
- fflush(stdout);
-
- if (scanf("%hd", &indexAttrNumber) != 1) {
- elog(NOTICE, "testbtree: attribute incorrectly specified");
- exitpg(0);
- }
-
- if (newIndex) {
- fprintf(stdout, "Operator class (421 = int2, 426 = int4): ");
- fflush(stdout);
-
- if (scanf("%hd", &indexAttrClass) != 1) {
- elog(NOTICE, "testbtree: class incorrectly specified");
- exitpg(0);
- }
- if (indexAttrClass != 421 && indexAttrClass != 426) {
- elog(NOTICE, "No such class, assuming int2.");
- indexAttrClass = 426;
- }
-
- fseek(stdin, 0, 2);
-
- beenHere = 1;
-
- DoCreateIndex(&heapNameData, &indexNameData,
- indexAttrNumber, indexAttrClass);
-
- }
-
- CommitTransactionCommand();
- StartTransactionCommand(portal);
-
- beenHere = 2;
-
- } else if (beenHere == 1) {
- elog(NOTICE, "testbtree: %s relation may exist--continuing!",
- indexNameData.data);
- beenHere = 2;
-
- } else if (beenHere > 1) {
- elog(FATAL, "testbtree: giving up!");
- }
-
- indexRelation = AMopenr(indexNameData.data); /* XXX */
- DoRuleLockInsertion(indexRelation);
- AMclose(indexRelation);
-
- QualificationState = UninitializedQualification;
-
- indexRelation = AMopenr(indexNameData.data); /* XXX */
- heapRelation = RelationNameOpenHeapRelation(heapNameData.data);
-
- RelationSetLockForRead(heapRelation);
-
- DoBTreeBrowse(indexRelation, heapRelation);
- DoForwardScan(indexRelation, heapRelation);
- DoBackwardScan(indexRelation, heapRelation);
-
- for (;;) {
- int status;
- NameData operatorNameData;
- ObjectId returnType;
-
- puts("\nPlease enter an operator and an integer value");
-
- fseek(stdin, 0, 2); /* discard any stuff on the input stream */
- status = scanf("%s%d", &(operatorNameData), &returnType);
-
- if (status <= 0) {
- break;
- } else if (status != 2) {
- elog(NOTICE, "testbtree: improper qualification specified");
- exitpg(0);
- }
-
- DoQualifiedScan(indexRelation, heapRelation, &operatorNameData,
- 0, returnType);
- }
-
- RelationCloseHeapRelation(heapRelation);
- RelationCloseIndexRelation(indexRelation);
-
- puts("\nDone!");
- CommitTransactionCommand();
- exitpg(0);
- }
-