📄 istrat.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: /usr/local/cvsroot/pgsql/src/backend/access/index/istrat.c,v 1.33.2.2 1999/08/02 05:56:39 scrappy Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/heapam.h"#include "access/istrat.h"#include "catalog/catname.h"#include "catalog/pg_amop.h"#include "catalog/pg_amproc.h"#include "catalog/pg_index.h"#include "catalog/pg_operator.h"#include "miscadmin.h"#include "utils/syscache.h"#ifdef USE_ASSERT_CHECKINGstatic 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 ScanKeyStrategyMapGetScanKeyEntry(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. */StrategyMapIndexStrategyGetStrategyMap(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. */SizeAttributeNumberGetIndexStrategySize(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 boolStrategyOperatorIsValid(StrategyOperator operator, StrategyNumber maxStrategy){ return (bool) (PointerIsValid(operator) && StrategyNumberIsInBounds(operator->strategy, maxStrategy) && !(operator->flags & ~(SK_NEGATE | SK_COMMUTE)));}/* ---------------- * StrategyTermIsValid * ---------------- */static boolStrategyTermIsValid(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 boolStrategyExpressionIsValid(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 boolStrategyEvaluationIsValid(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 boolStrategyTermEvaluate(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 * ---------------- */StrategyNumberRelationGetStrategy(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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -