1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-07 19:06:32 +03:00

Add operator strategy and comparison-value datatype fields to ScanKey.

Remove the 'strategy map' code, which was a large amount of mechanism
that no longer had any use except reverse-mapping from procedure OID to
strategy number.  Passing the strategy number to the index AM in the
first place is simpler and faster.
This is a preliminary step in planned support for cross-datatype index
operations.  I'm committing it now since the ScanKeyEntryInitialize()
API change touches quite a lot of files, and I want to commit those
changes before the tree drifts under me.
This commit is contained in:
Tom Lane
2003-11-09 21:30:38 +00:00
parent 723825afeb
commit c1d62bfd00
72 changed files with 950 additions and 2147 deletions

View File

@@ -4,7 +4,7 @@
# Makefile for access/index
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/access/index/Makefile,v 1.10 2000/08/31 16:09:36 petere Exp $
# $Header: /cvsroot/pgsql/src/backend/access/index/Makefile,v 1.11 2003/11/09 21:30:35 tgl Exp $
#
#-------------------------------------------------------------------------
@@ -12,7 +12,7 @@ subdir = src/backend/access/index
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
OBJS = genam.o indexam.o istrat.o
OBJS = genam.o indexam.o
all: SUBSYS.o

View File

@@ -1,479 +0,0 @@
/*-------------------------------------------------------------------------
*
* istrat.c
* index scan strategy manipulation code and index strategy manipulation
* operator code.
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.60 2003/08/04 02:39:57 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/istrat.h"
#ifdef USE_ASSERT_CHECKING
static bool StrategyEvaluationIsValid(StrategyEvaluation evaluation);
static bool StrategyExpressionIsValid(StrategyExpression expression,
StrategyNumber maxStrategy);
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.
*/
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
#ifdef NOT_USED
/* ----------------
* StrategyTermEvaluate
* ----------------
*/
static bool
StrategyTermEvaluate(StrategyTerm term,
StrategyMap map,
Datum left,
Datum right)
{
bool result = false;
Index index;
StrategyOperator operator;
for (index = 0, operator = &term->operatorData[0];
index < term->degree; index += 1, operator += 1)
{
ScanKey entry;
entry = &map->entry[operator->strategy - 1];
Assert(RegProcedureIsValid(entry->sk_procedure));
switch (operator->flags ^ entry->sk_flags)
{
case 0x0:
result = DatumGetBool(FunctionCall2(&entry->sk_func,
left, right));
break;
case SK_NEGATE:
result = !DatumGetBool(FunctionCall2(&entry->sk_func,
left, right));
break;
case SK_COMMUTE:
result = DatumGetBool(FunctionCall2(&entry->sk_func,
right, left));
break;
case SK_NEGATE | SK_COMMUTE:
result = !DatumGetBool(FunctionCall2(&entry->sk_func,
right, left));
break;
default:
elog(ERROR, "impossible strategy case: %d",
operator->flags ^ entry->sk_flags);
}
if (!result)
return result;
}
return result;
}
#endif
/* ----------------
* RelationGetStrategy
*
* Identify strategy number that describes given procedure, if there is one.
* ----------------
*/
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((attributeNumber >= 1) && (attributeNumber <= 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(ERROR, "impossible strategy case: %d",
entry->sk_flags);
}
if (!StrategyNumberIsInBounds(strategy, evaluation->maxStrategy))
{
if (!StrategyNumberIsValid(strategy))
elog(ERROR, "corrupted strategy evaluation");
}
return strategy;
}
#ifdef NOT_USED
/* ----------------
* 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, "cannot evaluate strategy %d", strategy);
/* not reached, just to make compiler happy */
return FALSE;
}
#endif
/* ----------------
* 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) */