732 lines
17 KiB
C
732 lines
17 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* istrat.c--
|
|
* index scan strategy manipulation code and index strategy manipulation
|
|
* operator code.
|
|
*
|
|
* Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
*
|
|
* IDENTIFICATION
|
|
* $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.18 1998/04/06 17:27:06 momjian Exp $
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include <postgres.h>
|
|
|
|
#include <catalog/pg_proc.h>
|
|
#include <catalog/pg_operator.h>
|
|
#include <catalog/catname.h>
|
|
#include <catalog/pg_index.h>
|
|
#include <catalog/pg_amop.h>
|
|
#include <catalog/pg_amproc.h>
|
|
#include <utils/memutils.h> /* could have been access/itup.h */
|
|
#include <access/heapam.h>
|
|
#include <access/istrat.h>
|
|
#include <fmgr.h>
|
|
|
|
#ifdef USE_ASSERT_CHECKING
|
|
static bool StrategyEvaluationIsValid(StrategyEvaluation evaluation);
|
|
static bool
|
|
StrategyExpressionIsValid(StrategyExpression expression,
|
|
StrategyNumber maxStrategy);
|
|
static ScanKey
|
|
StrategyMapGetScanKeyEntry(StrategyMap map,
|
|
StrategyNumber strategyNumber);
|
|
static bool
|
|
StrategyOperatorIsValid(StrategyOperator operator,
|
|
StrategyNumber maxStrategy);
|
|
static bool
|
|
StrategyTermIsValid(StrategyTerm term,
|
|
StrategyNumber maxStrategy);
|
|
|
|
#endif
|
|
|
|
|
|
/* ----------------------------------------------------------------
|
|
* misc strategy support routines
|
|
* ----------------------------------------------------------------
|
|
*/
|
|
|
|
/*
|
|
* StrategyNumberIsValid
|
|
* StrategyNumberIsInBounds
|
|
* StrategyMapIsValid
|
|
* StrategyTransformMapIsValid
|
|
* IndexStrategyIsValid
|
|
*
|
|
* ... are now macros in istrat.h -cim 4/27/91
|
|
*/
|
|
|
|
/*
|
|
* StrategyMapGetScanKeyEntry --
|
|
* Returns a scan key entry of a index strategy mapping member.
|
|
*
|
|
* Note:
|
|
* Assumes that the index strategy mapping is valid.
|
|
* Assumes that the index strategy number is valid.
|
|
* Bounds checking should be done outside this routine.
|
|
*/
|
|
static ScanKey
|
|
StrategyMapGetScanKeyEntry(StrategyMap map,
|
|
StrategyNumber strategyNumber)
|
|
{
|
|
Assert(StrategyMapIsValid(map));
|
|
Assert(StrategyNumberIsValid(strategyNumber));
|
|
return (&map->entry[strategyNumber - 1]);
|
|
}
|
|
|
|
/*
|
|
* IndexStrategyGetStrategyMap --
|
|
* Returns an index strategy mapping of an index strategy.
|
|
*
|
|
* Note:
|
|
* Assumes that the index strategy is valid.
|
|
* Assumes that the number of index strategies is valid.
|
|
* Bounds checking should be done outside this routine.
|
|
*/
|
|
StrategyMap
|
|
IndexStrategyGetStrategyMap(IndexStrategy indexStrategy,
|
|
StrategyNumber maxStrategyNum,
|
|
AttrNumber attrNum)
|
|
{
|
|
Assert(IndexStrategyIsValid(indexStrategy));
|
|
Assert(StrategyNumberIsValid(maxStrategyNum));
|
|
Assert(AttributeNumberIsValid(attrNum));
|
|
|
|
maxStrategyNum = AMStrategies(maxStrategyNum); /* XXX */
|
|
return
|
|
&indexStrategy->strategyMapData[maxStrategyNum * (attrNum - 1)];
|
|
}
|
|
|
|
/*
|
|
* AttributeNumberGetIndexStrategySize --
|
|
* Computes the size of an index strategy.
|
|
*/
|
|
Size
|
|
AttributeNumberGetIndexStrategySize(AttrNumber maxAttributeNumber,
|
|
StrategyNumber maxStrategyNumber)
|
|
{
|
|
maxStrategyNumber = AMStrategies(maxStrategyNumber); /* XXX */
|
|
return
|
|
maxAttributeNumber * maxStrategyNumber * sizeof(ScanKeyData);
|
|
}
|
|
|
|
#ifdef USE_ASSERT_CHECKING
|
|
/*
|
|
* StrategyTransformMapIsValid is now a macro in istrat.h -cim 4/27/91
|
|
*/
|
|
|
|
/* ----------------
|
|
* StrategyOperatorIsValid
|
|
* ----------------
|
|
*/
|
|
static bool
|
|
StrategyOperatorIsValid(StrategyOperator operator,
|
|
StrategyNumber maxStrategy)
|
|
{
|
|
return (bool)
|
|
(PointerIsValid(operator) &&
|
|
StrategyNumberIsInBounds(operator->strategy, maxStrategy) &&
|
|
!(operator->flags & ~(SK_NEGATE | SK_COMMUTE)));
|
|
}
|
|
|
|
/* ----------------
|
|
* StrategyTermIsValid
|
|
* ----------------
|
|
*/
|
|
static bool
|
|
StrategyTermIsValid(StrategyTerm term,
|
|
StrategyNumber maxStrategy)
|
|
{
|
|
Index index;
|
|
|
|
if (!PointerIsValid(term) || term->degree == 0)
|
|
return false;
|
|
|
|
for (index = 0; index < term->degree; index += 1)
|
|
{
|
|
if (!StrategyOperatorIsValid(&term->operatorData[index],
|
|
maxStrategy))
|
|
{
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* ----------------
|
|
* StrategyExpressionIsValid
|
|
* ----------------
|
|
*/
|
|
static bool
|
|
StrategyExpressionIsValid(StrategyExpression expression,
|
|
StrategyNumber maxStrategy)
|
|
{
|
|
StrategyTerm *termP;
|
|
|
|
if (!PointerIsValid(expression))
|
|
return true;
|
|
|
|
if (!StrategyTermIsValid(expression->term[0], maxStrategy))
|
|
return false;
|
|
|
|
termP = &expression->term[1];
|
|
while (StrategyTermIsValid(*termP, maxStrategy))
|
|
termP += 1;
|
|
|
|
return (bool)
|
|
(!PointerIsValid(*termP));
|
|
}
|
|
|
|
/* ----------------
|
|
* StrategyEvaluationIsValid
|
|
* ----------------
|
|
*/
|
|
static bool
|
|
StrategyEvaluationIsValid(StrategyEvaluation evaluation)
|
|
{
|
|
Index index;
|
|
|
|
if (!PointerIsValid(evaluation) ||
|
|
!StrategyNumberIsValid(evaluation->maxStrategy) ||
|
|
!StrategyTransformMapIsValid(evaluation->negateTransform) ||
|
|
!StrategyTransformMapIsValid(evaluation->commuteTransform) ||
|
|
!StrategyTransformMapIsValid(evaluation->negateCommuteTransform))
|
|
{
|
|
|
|
return false;
|
|
}
|
|
|
|
for (index = 0; index < evaluation->maxStrategy; index += 1)
|
|
{
|
|
if (!StrategyExpressionIsValid(evaluation->expression[index],
|
|
evaluation->maxStrategy))
|
|
{
|
|
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#endif
|
|
|
|
/* ----------------
|
|
* StrategyTermEvaluate
|
|
* ----------------
|
|
*/
|
|
static bool
|
|
StrategyTermEvaluate(StrategyTerm term,
|
|
StrategyMap map,
|
|
Datum left,
|
|
Datum right)
|
|
{
|
|
Index index;
|
|
long tmpres = 0;
|
|
bool result = 0;
|
|
StrategyOperator operator;
|
|
ScanKey entry;
|
|
|
|
for (index = 0, operator = &term->operatorData[0];
|
|
index < term->degree; index += 1, operator += 1)
|
|
{
|
|
|
|
entry = &map->entry[operator->strategy - 1];
|
|
|
|
Assert(RegProcedureIsValid(entry->sk_procedure));
|
|
|
|
switch (operator->flags ^ entry->sk_flags)
|
|
{
|
|
case 0x0:
|
|
tmpres = (long) FMGR_PTR2(&entry->sk_func,
|
|
left, right);
|
|
break;
|
|
|
|
case SK_NEGATE:
|
|
tmpres = (long) !FMGR_PTR2(&entry->sk_func,
|
|
left, right);
|
|
break;
|
|
|
|
case SK_COMMUTE:
|
|
tmpres = (long) FMGR_PTR2(&entry->sk_func,
|
|
right, left);
|
|
break;
|
|
|
|
case SK_NEGATE | SK_COMMUTE:
|
|
tmpres = (long) !FMGR_PTR2(&entry->sk_func,
|
|
right, left);
|
|
break;
|
|
|
|
default:
|
|
elog(FATAL, "StrategyTermEvaluate: impossible case %d",
|
|
operator->flags ^ entry->sk_flags);
|
|
}
|
|
|
|
result = (bool) tmpres;
|
|
if (!result)
|
|
return result;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* RelationGetStrategy
|
|
* ----------------
|
|
*/
|
|
StrategyNumber
|
|
RelationGetStrategy(Relation relation,
|
|
AttrNumber attributeNumber,
|
|
StrategyEvaluation evaluation,
|
|
RegProcedure procedure)
|
|
{
|
|
StrategyNumber strategy;
|
|
StrategyMap strategyMap;
|
|
ScanKey entry;
|
|
Index index;
|
|
int numattrs;
|
|
|
|
Assert(RelationIsValid(relation));
|
|
numattrs = RelationGetNumberOfAttributes(relation);
|
|
|
|
Assert(relation->rd_rel->relkind == RELKIND_INDEX); /* XXX use accessor */
|
|
Assert(AttributeNumberIsValid(attributeNumber));
|
|
Assert((attributeNumber >= 1) && (attributeNumber < 1 + numattrs));
|
|
|
|
Assert(StrategyEvaluationIsValid(evaluation));
|
|
Assert(RegProcedureIsValid(procedure));
|
|
|
|
strategyMap =
|
|
IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation),
|
|
evaluation->maxStrategy,
|
|
attributeNumber);
|
|
|
|
/* get a strategy number for the procedure ignoring flags for now */
|
|
for (index = 0; index < evaluation->maxStrategy; index += 1)
|
|
{
|
|
if (strategyMap->entry[index].sk_procedure == procedure)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (index == evaluation->maxStrategy)
|
|
return InvalidStrategy;
|
|
|
|
strategy = 1 + index;
|
|
entry = StrategyMapGetScanKeyEntry(strategyMap, strategy);
|
|
|
|
Assert(!(entry->sk_flags & ~(SK_NEGATE | SK_COMMUTE)));
|
|
|
|
switch (entry->sk_flags & (SK_NEGATE | SK_COMMUTE))
|
|
{
|
|
case 0x0:
|
|
return strategy;
|
|
|
|
case SK_NEGATE:
|
|
strategy = evaluation->negateTransform->strategy[strategy - 1];
|
|
break;
|
|
|
|
case SK_COMMUTE:
|
|
strategy = evaluation->commuteTransform->strategy[strategy - 1];
|
|
break;
|
|
|
|
case SK_NEGATE | SK_COMMUTE:
|
|
strategy = evaluation->negateCommuteTransform->strategy[strategy - 1];
|
|
break;
|
|
|
|
default:
|
|
elog(FATAL, "RelationGetStrategy: impossible case %d", entry->sk_flags);
|
|
}
|
|
|
|
|
|
if (!StrategyNumberIsInBounds(strategy, evaluation->maxStrategy))
|
|
{
|
|
if (!StrategyNumberIsValid(strategy))
|
|
{
|
|
elog(ERROR, "RelationGetStrategy: corrupted evaluation");
|
|
}
|
|
}
|
|
|
|
return strategy;
|
|
}
|
|
|
|
/* ----------------
|
|
* RelationInvokeStrategy
|
|
* ----------------
|
|
*/
|
|
bool /* XXX someday, this may return Datum */
|
|
RelationInvokeStrategy(Relation relation,
|
|
StrategyEvaluation evaluation,
|
|
AttrNumber attributeNumber,
|
|
StrategyNumber strategy,
|
|
Datum left,
|
|
Datum right)
|
|
{
|
|
StrategyNumber newStrategy;
|
|
StrategyMap strategyMap;
|
|
ScanKey entry;
|
|
StrategyTermData termData;
|
|
int numattrs;
|
|
|
|
Assert(RelationIsValid(relation));
|
|
Assert(relation->rd_rel->relkind == RELKIND_INDEX); /* XXX use accessor */
|
|
numattrs = RelationGetNumberOfAttributes(relation);
|
|
|
|
Assert(StrategyEvaluationIsValid(evaluation));
|
|
Assert(AttributeNumberIsValid(attributeNumber));
|
|
Assert((attributeNumber >= 1) && (attributeNumber < 1 + numattrs));
|
|
|
|
Assert(StrategyNumberIsInBounds(strategy, evaluation->maxStrategy));
|
|
|
|
termData.degree = 1;
|
|
|
|
strategyMap =
|
|
IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation),
|
|
evaluation->maxStrategy,
|
|
attributeNumber);
|
|
|
|
entry = StrategyMapGetScanKeyEntry(strategyMap, strategy);
|
|
|
|
if (RegProcedureIsValid(entry->sk_procedure))
|
|
{
|
|
termData.operatorData[0].strategy = strategy;
|
|
termData.operatorData[0].flags = 0x0;
|
|
|
|
return
|
|
StrategyTermEvaluate(&termData, strategyMap, left, right);
|
|
}
|
|
|
|
|
|
newStrategy = evaluation->negateTransform->strategy[strategy - 1];
|
|
if (newStrategy != strategy && StrategyNumberIsValid(newStrategy))
|
|
{
|
|
|
|
entry = StrategyMapGetScanKeyEntry(strategyMap, newStrategy);
|
|
|
|
if (RegProcedureIsValid(entry->sk_procedure))
|
|
{
|
|
termData.operatorData[0].strategy = newStrategy;
|
|
termData.operatorData[0].flags = SK_NEGATE;
|
|
|
|
return
|
|
StrategyTermEvaluate(&termData, strategyMap, left, right);
|
|
}
|
|
}
|
|
|
|
newStrategy = evaluation->commuteTransform->strategy[strategy - 1];
|
|
if (newStrategy != strategy && StrategyNumberIsValid(newStrategy))
|
|
{
|
|
|
|
entry = StrategyMapGetScanKeyEntry(strategyMap, newStrategy);
|
|
|
|
if (RegProcedureIsValid(entry->sk_procedure))
|
|
{
|
|
termData.operatorData[0].strategy = newStrategy;
|
|
termData.operatorData[0].flags = SK_COMMUTE;
|
|
|
|
return
|
|
StrategyTermEvaluate(&termData, strategyMap, left, right);
|
|
}
|
|
}
|
|
|
|
newStrategy = evaluation->negateCommuteTransform->strategy[strategy - 1];
|
|
if (newStrategy != strategy && StrategyNumberIsValid(newStrategy))
|
|
{
|
|
|
|
entry = StrategyMapGetScanKeyEntry(strategyMap, newStrategy);
|
|
|
|
if (RegProcedureIsValid(entry->sk_procedure))
|
|
{
|
|
termData.operatorData[0].strategy = newStrategy;
|
|
termData.operatorData[0].flags = SK_NEGATE | SK_COMMUTE;
|
|
|
|
return
|
|
StrategyTermEvaluate(&termData, strategyMap, left, right);
|
|
}
|
|
}
|
|
|
|
if (PointerIsValid(evaluation->expression[strategy - 1]))
|
|
{
|
|
StrategyTerm *termP;
|
|
|
|
termP = &evaluation->expression[strategy - 1]->term[0];
|
|
while (PointerIsValid(*termP))
|
|
{
|
|
Index index;
|
|
|
|
for (index = 0; index < (*termP)->degree; index += 1)
|
|
{
|
|
entry = StrategyMapGetScanKeyEntry(strategyMap,
|
|
(*termP)->operatorData[index].strategy);
|
|
|
|
if (!RegProcedureIsValid(entry->sk_procedure))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (index == (*termP)->degree)
|
|
{
|
|
return
|
|
StrategyTermEvaluate(*termP, strategyMap, left, right);
|
|
}
|
|
|
|
termP += 1;
|
|
}
|
|
}
|
|
|
|
elog(ERROR, "RelationInvokeStrategy: cannot evaluate strategy %d",
|
|
strategy);
|
|
|
|
/* not reached, just to make compiler happy */
|
|
return FALSE;
|
|
|
|
|
|
}
|
|
|
|
/* ----------------
|
|
* OperatorRelationFillScanKeyEntry
|
|
* ----------------
|
|
*/
|
|
static void
|
|
OperatorRelationFillScanKeyEntry(Relation operatorRelation,
|
|
Oid operatorObjectId,
|
|
ScanKey entry)
|
|
{
|
|
HeapScanDesc scan;
|
|
ScanKeyData scanKeyData;
|
|
HeapTuple tuple;
|
|
|
|
ScanKeyEntryInitialize(&scanKeyData, 0,
|
|
ObjectIdAttributeNumber,
|
|
ObjectIdEqualRegProcedure,
|
|
ObjectIdGetDatum(operatorObjectId));
|
|
|
|
scan = heap_beginscan(operatorRelation, false, false,
|
|
1, &scanKeyData);
|
|
|
|
tuple = heap_getnext(scan, false, (Buffer *) NULL);
|
|
if (!HeapTupleIsValid(tuple))
|
|
{
|
|
elog(ERROR, "OperatorObjectIdFillScanKeyEntry: unknown operator %lu",
|
|
(uint32) operatorObjectId);
|
|
}
|
|
|
|
entry->sk_flags = 0;
|
|
entry->sk_procedure =
|
|
((OperatorTupleForm) GETSTRUCT(tuple))->oprcode;
|
|
fmgr_info(entry->sk_procedure, &entry->sk_func);
|
|
entry->sk_nargs = entry->sk_func.fn_nargs;
|
|
|
|
if (!RegProcedureIsValid(entry->sk_procedure))
|
|
{
|
|
elog(ERROR,
|
|
"OperatorObjectIdFillScanKeyEntry: no procedure for operator %lu",
|
|
(uint32) operatorObjectId);
|
|
}
|
|
|
|
heap_endscan(scan);
|
|
}
|
|
|
|
|
|
/*
|
|
* IndexSupportInitialize --
|
|
* Initializes an index strategy and associated support procedures.
|
|
*/
|
|
void
|
|
IndexSupportInitialize(IndexStrategy indexStrategy,
|
|
RegProcedure *indexSupport,
|
|
Oid indexObjectId,
|
|
Oid accessMethodObjectId,
|
|
StrategyNumber maxStrategyNumber,
|
|
StrategyNumber maxSupportNumber,
|
|
AttrNumber maxAttributeNumber)
|
|
{
|
|
Relation relation;
|
|
Relation operatorRelation;
|
|
HeapScanDesc scan;
|
|
HeapTuple tuple;
|
|
ScanKeyData entry[2];
|
|
StrategyMap map;
|
|
AttrNumber attributeNumber;
|
|
int attributeIndex;
|
|
Oid operatorClassObjectId[MaxIndexAttributeNumber];
|
|
|
|
maxStrategyNumber = AMStrategies(maxStrategyNumber);
|
|
|
|
ScanKeyEntryInitialize(&entry[0], 0, Anum_pg_index_indexrelid,
|
|
ObjectIdEqualRegProcedure,
|
|
ObjectIdGetDatum(indexObjectId));
|
|
|
|
relation = heap_openr(IndexRelationName);
|
|
scan = heap_beginscan(relation, false, false, 1, entry);
|
|
tuple = heap_getnext(scan, 0, (Buffer *) NULL);
|
|
if (!HeapTupleIsValid(tuple))
|
|
elog(ERROR, "IndexSupportInitialize: corrupted catalogs");
|
|
|
|
/*
|
|
* XXX note that the following assumes the INDEX tuple is well formed
|
|
* and that the key[] and class[] are 0 terminated.
|
|
*/
|
|
for (attributeIndex = 0; attributeIndex < maxAttributeNumber; attributeIndex++)
|
|
{
|
|
IndexTupleForm iform;
|
|
|
|
iform = (IndexTupleForm) GETSTRUCT(tuple);
|
|
|
|
if (!OidIsValid(iform->indkey[attributeIndex]))
|
|
{
|
|
if (attributeIndex == 0)
|
|
{
|
|
elog(ERROR, "IndexSupportInitialize: no pg_index tuple");
|
|
}
|
|
break;
|
|
}
|
|
|
|
operatorClassObjectId[attributeIndex]
|
|
= iform->indclass[attributeIndex];
|
|
}
|
|
|
|
heap_endscan(scan);
|
|
heap_close(relation);
|
|
|
|
/* if support routines exist for this access method, load them */
|
|
if (maxSupportNumber > 0)
|
|
{
|
|
|
|
ScanKeyEntryInitialize(&entry[0], 0, Anum_pg_amproc_amid,
|
|
ObjectIdEqualRegProcedure,
|
|
ObjectIdGetDatum(accessMethodObjectId));
|
|
|
|
ScanKeyEntryInitialize(&entry[1], 0, Anum_pg_amproc_amopclaid,
|
|
ObjectIdEqualRegProcedure, 0);
|
|
|
|
/* relation = heap_openr(Name_pg_amproc); */
|
|
relation = heap_openr(AccessMethodProcedureRelationName);
|
|
|
|
|
|
for (attributeNumber = maxAttributeNumber; attributeNumber > 0;
|
|
attributeNumber--)
|
|
{
|
|
|
|
int16 support;
|
|
Form_pg_amproc form;
|
|
RegProcedure *loc;
|
|
|
|
loc = &indexSupport[((attributeNumber - 1) * maxSupportNumber)];
|
|
|
|
for (support = maxSupportNumber; --support >= 0;)
|
|
{
|
|
loc[support] = InvalidOid;
|
|
}
|
|
|
|
entry[1].sk_argument =
|
|
ObjectIdGetDatum(operatorClassObjectId[attributeNumber - 1]);
|
|
|
|
scan = heap_beginscan(relation, false, false, 2, entry);
|
|
|
|
while (tuple = heap_getnext(scan, 0, (Buffer *) NULL),
|
|
HeapTupleIsValid(tuple))
|
|
{
|
|
|
|
form = (Form_pg_amproc) GETSTRUCT(tuple);
|
|
loc[(form->amprocnum - 1)] = form->amproc;
|
|
}
|
|
|
|
heap_endscan(scan);
|
|
}
|
|
heap_close(relation);
|
|
}
|
|
|
|
ScanKeyEntryInitialize(&entry[0], 0,
|
|
Anum_pg_amop_amopid,
|
|
ObjectIdEqualRegProcedure,
|
|
ObjectIdGetDatum(accessMethodObjectId));
|
|
|
|
ScanKeyEntryInitialize(&entry[1], 0,
|
|
Anum_pg_amop_amopclaid,
|
|
ObjectIdEqualRegProcedure, 0);
|
|
|
|
relation = heap_openr(AccessMethodOperatorRelationName);
|
|
operatorRelation = heap_openr(OperatorRelationName);
|
|
|
|
for (attributeNumber = maxAttributeNumber; attributeNumber > 0;
|
|
attributeNumber--)
|
|
{
|
|
|
|
StrategyNumber strategy;
|
|
|
|
entry[1].sk_argument =
|
|
ObjectIdGetDatum(operatorClassObjectId[attributeNumber - 1]);
|
|
|
|
map = IndexStrategyGetStrategyMap(indexStrategy,
|
|
maxStrategyNumber,
|
|
attributeNumber);
|
|
|
|
for (strategy = 1; strategy <= maxStrategyNumber; strategy++)
|
|
ScanKeyEntrySetIllegal(StrategyMapGetScanKeyEntry(map, strategy));
|
|
|
|
scan = heap_beginscan(relation, false, false, 2, entry);
|
|
|
|
while (tuple = heap_getnext(scan, 0, (Buffer *) NULL),
|
|
HeapTupleIsValid(tuple))
|
|
{
|
|
Form_pg_amop form;
|
|
|
|
form = (Form_pg_amop) GETSTRUCT(tuple);
|
|
|
|
OperatorRelationFillScanKeyEntry(operatorRelation,
|
|
form->amopopr,
|
|
StrategyMapGetScanKeyEntry(map, form->amopstrategy));
|
|
}
|
|
|
|
heap_endscan(scan);
|
|
}
|
|
|
|
heap_close(operatorRelation);
|
|
heap_close(relation);
|
|
}
|
|
|
|
/* ----------------
|
|
* IndexStrategyDisplay
|
|
* ----------------
|
|
*/
|
|
#ifdef ISTRATDEBUG
|
|
int
|
|
IndexStrategyDisplay(IndexStrategy indexStrategy,
|
|
StrategyNumber numberOfStrategies,
|
|
int numberOfAttributes)
|
|
{
|
|
StrategyMap strategyMap;
|
|
AttrNumber attributeNumber;
|
|
StrategyNumber strategyNumber;
|
|
|
|
for (attributeNumber = 1; attributeNumber <= numberOfAttributes;
|
|
attributeNumber += 1)
|
|
{
|
|
|
|
strategyMap = IndexStrategyGetStrategyMap(indexStrategy,
|
|
numberOfStrategies,
|
|
attributeNumber);
|
|
|
|
for (strategyNumber = 1;
|
|
strategyNumber <= AMStrategies(numberOfStrategies);
|
|
strategyNumber += 1)
|
|
{
|
|
|
|
printf(":att %d\t:str %d\t:opr 0x%x(%d)\n",
|
|
attributeNumber, strategyNumber,
|
|
strategyMap->entry[strategyNumber - 1].sk_procedure,
|
|
strategyMap->entry[strategyNumber - 1].sk_procedure);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* defined(ISTRATDEBUG) */
|