1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* defind.c--
|
|
|
|
* POSTGRES define, extend and remove index code.
|
|
|
|
*
|
|
|
|
* Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
1996-11-13 21:56:15 +01:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/defind.c,v 1.9 1996/11/13 20:48:22 scrappy Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
1996-11-04 00:57:43 +01:00
|
|
|
#include <string.h>
|
|
|
|
|
1996-11-06 09:21:43 +01:00
|
|
|
#include <postgres.h>
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-11-06 09:21:43 +01:00
|
|
|
#include <access/attnum.h>
|
|
|
|
#include <access/genam.h>
|
|
|
|
#include <access/heapam.h>
|
|
|
|
#include <utils/builtins.h>
|
|
|
|
#include <utils/syscache.h>
|
|
|
|
#include <catalog/index.h>
|
|
|
|
#include <catalog/pg_index.h>
|
|
|
|
#include <catalog/pg_proc.h>
|
|
|
|
#include <catalog/pg_opclass.h>
|
|
|
|
#include <nodes/plannodes.h>
|
|
|
|
#include <nodes/primnodes.h>
|
|
|
|
#include <nodes/relation.h>
|
|
|
|
#include <utils/relcache.h>
|
|
|
|
#include <utils/lsyscache.h>
|
|
|
|
#include <commands/defrem.h>
|
|
|
|
#include <parser/parsetree.h> /* for getrelid() */
|
|
|
|
#include <optimizer/prep.h>
|
|
|
|
#include <optimizer/clauses.h>
|
|
|
|
#include <storage/lmgr.h>
|
|
|
|
#include <fmgr.h>
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
#define IsFuncIndex(ATTR_LIST) (((IndexElem*)lfirst(ATTR_LIST))->args!=NULL)
|
|
|
|
|
|
|
|
/* non-export function prototypes */
|
|
|
|
static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid);
|
|
|
|
static void CheckPredExpr(Node *predicate, List *rangeTable,
|
|
|
|
Oid baseRelOid);
|
|
|
|
static void
|
|
|
|
CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid);
|
|
|
|
static void FuncIndexArgs(IndexElem *funcIndex, AttrNumber *attNumP,
|
|
|
|
Oid *argTypes, Oid *opOidP, Oid relId);
|
|
|
|
static void NormIndexAttrs(List *attList, AttrNumber *attNumP,
|
|
|
|
Oid *opOidP, Oid relId);
|
1996-08-15 09:42:52 +02:00
|
|
|
static char *GetDefaultOpClass(Oid atttypid);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* DefineIndex --
|
|
|
|
* Creates a new index.
|
|
|
|
*
|
|
|
|
* 'attributeList' is a list of IndexElem specifying either a functional
|
|
|
|
* index or a list of attributes to index on.
|
|
|
|
* 'parameterList' is a list of ParamString specified in the with clause.
|
|
|
|
* 'predicate' is the qual specified in the where clause.
|
|
|
|
* 'rangetable' is for the predicate
|
|
|
|
*
|
|
|
|
* Exceptions:
|
|
|
|
* XXX
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
DefineIndex(char *heapRelationName,
|
|
|
|
char *indexRelationName,
|
|
|
|
char *accessMethodName,
|
|
|
|
List *attributeList,
|
|
|
|
List *parameterList,
|
1996-11-13 21:56:15 +01:00
|
|
|
bool unique,
|
1996-07-09 08:22:35 +02:00
|
|
|
Expr *predicate,
|
|
|
|
List *rangetable)
|
|
|
|
{
|
|
|
|
Oid *classObjectId;
|
|
|
|
Oid accessMethodId;
|
|
|
|
Oid relationId;
|
|
|
|
int numberOfAttributes;
|
|
|
|
AttrNumber *attributeNumberA;
|
|
|
|
HeapTuple tuple;
|
|
|
|
uint16 parameterCount = 0;
|
|
|
|
Datum *parameterA = NULL;
|
|
|
|
FuncIndexInfo fInfo;
|
|
|
|
List *cnfPred = NULL;
|
1996-08-26 08:32:06 +02:00
|
|
|
bool lossy = FALSE;
|
|
|
|
List *pl;
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
|
|
|
* Handle attributes
|
|
|
|
*/
|
|
|
|
numberOfAttributes = length(attributeList);
|
|
|
|
if (numberOfAttributes <= 0) {
|
|
|
|
elog(WARN, "DefineIndex: must specify at least one attribute");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* compute heap relation id
|
|
|
|
*/
|
|
|
|
tuple = SearchSysCacheTuple(RELNAME,
|
|
|
|
PointerGetDatum(heapRelationName),
|
|
|
|
0,0,0);
|
|
|
|
if (!HeapTupleIsValid(tuple)) {
|
|
|
|
elog(WARN, "DefineIndex: %s relation not found",
|
|
|
|
heapRelationName);
|
|
|
|
}
|
|
|
|
relationId = tuple->t_oid;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* compute access method id
|
|
|
|
*/
|
|
|
|
tuple = SearchSysCacheTuple(AMNAME, PointerGetDatum(accessMethodName),
|
|
|
|
0,0,0);
|
|
|
|
if (!HeapTupleIsValid(tuple)) {
|
|
|
|
elog(WARN, "DefineIndex: %s access method not found",
|
|
|
|
accessMethodName);
|
|
|
|
}
|
|
|
|
accessMethodId = tuple->t_oid;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle parameters
|
|
|
|
* [param list is now different (NOT USED, really) - ay 10/94]
|
1996-08-26 08:32:06 +02:00
|
|
|
*
|
|
|
|
* WITH clause reinstated to handle lossy indices.
|
|
|
|
* -- JMH, 7/22/96
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1996-08-26 08:32:06 +02:00
|
|
|
foreach(pl, parameterList) {
|
|
|
|
ParamString *param = (ParamString*)lfirst(pl);
|
|
|
|
|
|
|
|
if (!strcasecmp(param->name, "islossy"))
|
|
|
|
lossy = TRUE;
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert the partial-index predicate from parsetree form to plan
|
|
|
|
* form, so it can be readily evaluated during index creation.
|
|
|
|
* Note: "predicate" comes in as a list containing (1) the predicate
|
|
|
|
* itself (a where_clause), and (2) a corresponding range table.
|
|
|
|
*
|
|
|
|
* [(1) is 'predicate' and (2) is 'rangetable' now. - ay 10/94]
|
|
|
|
*/
|
|
|
|
if (predicate != NULL && rangetable != NIL) {
|
|
|
|
cnfPred = cnfify((Expr*)copyObject(predicate), true);
|
|
|
|
fix_opids(cnfPred);
|
|
|
|
CheckPredicate(cnfPred, rangetable, relationId);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsFuncIndex(attributeList)) {
|
|
|
|
IndexElem *funcIndex= lfirst(attributeList);
|
|
|
|
int nargs;
|
|
|
|
|
|
|
|
nargs = length(funcIndex->args);
|
|
|
|
if (nargs > INDEX_MAX_KEYS) {
|
|
|
|
elog(WARN,
|
|
|
|
"Too many args to function, limit of %d",
|
|
|
|
INDEX_MAX_KEYS);
|
|
|
|
}
|
|
|
|
|
|
|
|
FIsetnArgs(&fInfo,nargs);
|
|
|
|
|
|
|
|
strcpy(FIgetname(&fInfo), funcIndex->name);
|
|
|
|
|
|
|
|
attributeNumberA =
|
|
|
|
(AttrNumber *)palloc(nargs * sizeof attributeNumberA[0]);
|
|
|
|
|
|
|
|
classObjectId = (Oid *)palloc(sizeof classObjectId[0]);
|
|
|
|
|
|
|
|
|
|
|
|
FuncIndexArgs(funcIndex, attributeNumberA,
|
|
|
|
&(FIgetArg(&fInfo, 0)),
|
|
|
|
classObjectId, relationId);
|
|
|
|
|
|
|
|
index_create(heapRelationName,
|
|
|
|
indexRelationName,
|
1996-08-26 08:32:06 +02:00
|
|
|
&fInfo, NULL, accessMethodId,
|
1996-07-09 08:22:35 +02:00
|
|
|
numberOfAttributes, attributeNumberA,
|
1996-08-26 08:32:06 +02:00
|
|
|
classObjectId, parameterCount, parameterA, (Node*)cnfPred,
|
1996-11-13 21:56:15 +01:00
|
|
|
lossy, unique);
|
1996-07-09 08:22:35 +02:00
|
|
|
}else {
|
|
|
|
attributeNumberA =
|
|
|
|
(AttrNumber *)palloc(numberOfAttributes *
|
|
|
|
sizeof attributeNumberA[0]);
|
|
|
|
|
|
|
|
classObjectId =
|
|
|
|
(Oid *)palloc(numberOfAttributes * sizeof classObjectId[0]);
|
|
|
|
|
|
|
|
NormIndexAttrs(attributeList, attributeNumberA,
|
|
|
|
classObjectId, relationId);
|
|
|
|
|
|
|
|
index_create(heapRelationName, indexRelationName, NULL,
|
1996-08-26 08:32:06 +02:00
|
|
|
((IndexElem*)lfirst(attributeList))->tname,
|
1996-07-09 08:22:35 +02:00
|
|
|
accessMethodId, numberOfAttributes, attributeNumberA,
|
1996-08-26 08:32:06 +02:00
|
|
|
classObjectId, parameterCount, parameterA, (Node*)cnfPred,
|
1996-11-13 21:56:15 +01:00
|
|
|
lossy, unique);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ExtendIndex --
|
|
|
|
* Extends a partial index.
|
|
|
|
*
|
|
|
|
* Exceptions:
|
|
|
|
* XXX
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
|
|
|
|
{
|
|
|
|
Oid *classObjectId;
|
|
|
|
Oid accessMethodId;
|
|
|
|
Oid indexId, relationId;
|
|
|
|
Oid indproc;
|
|
|
|
int numberOfAttributes;
|
|
|
|
AttrNumber *attributeNumberA;
|
|
|
|
HeapTuple tuple;
|
|
|
|
FuncIndexInfo fInfo;
|
|
|
|
FuncIndexInfo *funcInfo = NULL;
|
|
|
|
IndexTupleForm index;
|
|
|
|
Node *oldPred = NULL;
|
|
|
|
List *cnfPred = NULL;
|
|
|
|
PredInfo *predInfo;
|
|
|
|
Relation heapRelation;
|
|
|
|
Relation indexRelation;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* compute index relation id and access method id
|
|
|
|
*/
|
|
|
|
tuple = SearchSysCacheTuple(RELNAME, PointerGetDatum(indexRelationName),
|
|
|
|
0,0,0);
|
|
|
|
if (!HeapTupleIsValid(tuple)) {
|
|
|
|
elog(WARN, "ExtendIndex: %s index not found",
|
|
|
|
indexRelationName);
|
|
|
|
}
|
|
|
|
indexId = tuple->t_oid;
|
|
|
|
accessMethodId = ((Form_pg_class) GETSTRUCT(tuple))->relam;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* find pg_index tuple
|
|
|
|
*/
|
|
|
|
tuple = SearchSysCacheTuple(INDEXRELID,
|
|
|
|
ObjectIdGetDatum(indexId),
|
|
|
|
0,0,0);
|
|
|
|
if (!HeapTupleIsValid(tuple)) {
|
|
|
|
elog(WARN, "ExtendIndex: %s is not an index",
|
|
|
|
indexRelationName);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Extract info from the pg_index tuple
|
|
|
|
*/
|
|
|
|
index = (IndexTupleForm)GETSTRUCT(tuple);
|
|
|
|
Assert(index->indexrelid == indexId);
|
|
|
|
relationId = index->indrelid;
|
|
|
|
indproc = index->indproc;
|
|
|
|
|
|
|
|
for (i=0; i<INDEX_MAX_KEYS; i++)
|
|
|
|
if (index->indkey[i] == 0) break;
|
|
|
|
numberOfAttributes = i;
|
|
|
|
|
|
|
|
if (VARSIZE(&index->indpred) != 0) {
|
|
|
|
char *predString;
|
|
|
|
|
|
|
|
predString = fmgr(F_TEXTOUT, &index->indpred);
|
|
|
|
oldPred = stringToNode(predString);
|
|
|
|
pfree(predString);
|
|
|
|
}
|
|
|
|
if (oldPred == NULL)
|
|
|
|
elog(WARN, "ExtendIndex: %s is not a partial index",
|
|
|
|
indexRelationName);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert the extension predicate from parsetree form to plan
|
|
|
|
* form, so it can be readily evaluated during index creation.
|
|
|
|
* Note: "predicate" comes in as a list containing (1) the predicate
|
|
|
|
* itself (a where_clause), and (2) a corresponding range table.
|
|
|
|
*/
|
|
|
|
if (rangetable != NIL) {
|
|
|
|
cnfPred = cnfify((Expr*)copyObject(predicate), true);
|
|
|
|
fix_opids(cnfPred);
|
|
|
|
CheckPredicate(cnfPred, rangetable, relationId);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* make predInfo list to pass to index_build */
|
|
|
|
predInfo = (PredInfo*)palloc(sizeof(PredInfo));
|
|
|
|
predInfo->pred = (Node*)cnfPred;
|
|
|
|
predInfo->oldPred = oldPred;
|
|
|
|
|
|
|
|
attributeNumberA =
|
|
|
|
(AttrNumber *)palloc(numberOfAttributes*
|
|
|
|
sizeof attributeNumberA[0]);
|
|
|
|
classObjectId =
|
|
|
|
(Oid *)palloc(numberOfAttributes * sizeof classObjectId[0]);
|
|
|
|
|
|
|
|
|
|
|
|
for (i=0; i<numberOfAttributes; i++) {
|
|
|
|
attributeNumberA[i] = index->indkey[i];
|
|
|
|
classObjectId[i] = index->indclass[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (indproc != InvalidOid) {
|
|
|
|
funcInfo = &fInfo;
|
|
|
|
/* FIgetnArgs(funcInfo) = numberOfAttributes; */
|
|
|
|
FIsetnArgs(funcInfo,numberOfAttributes);
|
|
|
|
|
|
|
|
tuple = SearchSysCacheTuple(PROOID,
|
|
|
|
ObjectIdGetDatum(indproc),
|
|
|
|
0,0,0);
|
|
|
|
if (!HeapTupleIsValid(tuple))
|
|
|
|
elog(WARN, "ExtendIndex: index procedure not found");
|
|
|
|
|
|
|
|
namecpy(&(funcInfo->funcName),
|
|
|
|
&(((Form_pg_proc) GETSTRUCT(tuple))->proname));
|
|
|
|
|
|
|
|
FIsetProcOid(funcInfo,tuple->t_oid);
|
|
|
|
}
|
|
|
|
|
|
|
|
heapRelation = heap_open(relationId);
|
|
|
|
indexRelation = index_open(indexId);
|
|
|
|
|
|
|
|
RelationSetLockForWrite(heapRelation);
|
|
|
|
|
|
|
|
InitIndexStrategy(numberOfAttributes, indexRelation, accessMethodId);
|
|
|
|
|
|
|
|
index_build(heapRelation, indexRelation, numberOfAttributes,
|
|
|
|
attributeNumberA, 0, NULL, funcInfo, predInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* CheckPredicate
|
|
|
|
* Checks that the given list of partial-index predicates refer
|
|
|
|
* (via the given range table) only to the given base relation oid,
|
|
|
|
* and that they're in a form the planner can handle, i.e.,
|
|
|
|
* boolean combinations of "ATTR OP CONST" (yes, for now, the ATTR
|
|
|
|
* has to be on the left).
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid)
|
|
|
|
{
|
|
|
|
List *item;
|
|
|
|
|
|
|
|
foreach (item, predList) {
|
|
|
|
CheckPredExpr(lfirst(item), rangeTable, baseRelOid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid)
|
|
|
|
{
|
|
|
|
List *clauses = NIL, *clause;
|
|
|
|
|
|
|
|
if (is_opclause(predicate)) {
|
|
|
|
CheckPredClause((Expr*)predicate, rangeTable, baseRelOid);
|
|
|
|
return;
|
|
|
|
} else if (or_clause(predicate))
|
|
|
|
clauses = ((Expr*)predicate)->args;
|
|
|
|
else if (and_clause(predicate))
|
|
|
|
clauses = ((Expr*)predicate)->args;
|
|
|
|
else
|
|
|
|
elog(WARN, "Unsupported partial-index predicate expression type");
|
|
|
|
|
|
|
|
foreach (clause, clauses) {
|
|
|
|
CheckPredExpr(lfirst(clause), rangeTable, baseRelOid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid)
|
|
|
|
{
|
|
|
|
Var *pred_var;
|
|
|
|
Const *pred_const;
|
|
|
|
|
|
|
|
pred_var = (Var *)get_leftop(predicate);
|
|
|
|
pred_const = (Const *)get_rightop(predicate);
|
|
|
|
|
|
|
|
if (!IsA(predicate->oper,Oper) ||
|
|
|
|
!IsA(pred_var,Var) ||
|
|
|
|
!IsA(pred_const,Const)) {
|
|
|
|
elog(WARN, "Unsupported partial-index predicate clause type");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getrelid(pred_var->varno, rangeTable) != baseRelOid)
|
|
|
|
elog(WARN,
|
|
|
|
"Partial-index predicates may refer only to the base relation");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
FuncIndexArgs(IndexElem *funcIndex,
|
|
|
|
AttrNumber *attNumP,
|
|
|
|
Oid *argTypes,
|
|
|
|
Oid *opOidP,
|
|
|
|
Oid relId)
|
|
|
|
{
|
|
|
|
List *rest;
|
|
|
|
HeapTuple tuple;
|
|
|
|
AttributeTupleForm att;
|
|
|
|
|
|
|
|
tuple = SearchSysCacheTuple(CLANAME,
|
|
|
|
PointerGetDatum(funcIndex->class),
|
|
|
|
0,0,0);
|
|
|
|
|
|
|
|
if (!HeapTupleIsValid(tuple))
|
|
|
|
{
|
|
|
|
elog(WARN, "DefineIndex: %s class not found",
|
|
|
|
funcIndex->class);
|
|
|
|
}
|
|
|
|
*opOidP = tuple->t_oid;
|
|
|
|
|
|
|
|
memset(argTypes, 0, 8 * sizeof(Oid));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* process the function arguments
|
|
|
|
*/
|
|
|
|
for (rest=funcIndex->args; rest != NIL; rest = lnext(rest)) {
|
|
|
|
char *arg;
|
|
|
|
|
|
|
|
arg = strVal(lfirst(rest));
|
|
|
|
|
|
|
|
tuple = SearchSysCacheTuple(ATTNAME,
|
|
|
|
ObjectIdGetDatum(relId),
|
|
|
|
PointerGetDatum(arg),0,0);
|
|
|
|
|
|
|
|
if (!HeapTupleIsValid(tuple)) {
|
|
|
|
elog(WARN,
|
|
|
|
"DefineIndex: attribute \"%s\" not found",
|
|
|
|
arg);
|
|
|
|
}
|
|
|
|
att = (AttributeTupleForm)GETSTRUCT(tuple);
|
|
|
|
*attNumP++ = att->attnum;
|
|
|
|
*argTypes++ = att->atttypid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
NormIndexAttrs(List *attList, /* list of IndexElem's */
|
|
|
|
AttrNumber *attNumP,
|
|
|
|
Oid *opOidP,
|
|
|
|
Oid relId)
|
|
|
|
{
|
|
|
|
List *rest;
|
|
|
|
HeapTuple tuple;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* process attributeList
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (rest=attList; rest != NIL; rest = lnext(rest)) {
|
|
|
|
IndexElem *attribute;
|
1996-08-15 09:42:52 +02:00
|
|
|
AttributeTupleForm attform;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
attribute = lfirst(rest);
|
|
|
|
|
|
|
|
if (attribute->name == NULL)
|
|
|
|
elog(WARN, "missing attribute for define index");
|
|
|
|
|
|
|
|
tuple = SearchSysCacheTuple(ATTNAME,
|
|
|
|
ObjectIdGetDatum(relId),
|
|
|
|
PointerGetDatum(attribute->name),
|
|
|
|
0,0);
|
|
|
|
if (!HeapTupleIsValid(tuple)) {
|
|
|
|
elog(WARN,
|
|
|
|
"DefineIndex: attribute \"%s\" not found",
|
|
|
|
attribute->name);
|
|
|
|
}
|
1996-08-15 09:42:52 +02:00
|
|
|
|
|
|
|
attform = (AttributeTupleForm)GETSTRUCT(tuple);
|
|
|
|
*attNumP++ = attform->attnum;
|
|
|
|
|
|
|
|
if (attribute->class == NULL) {
|
|
|
|
/* no operator class specified, so find the default */
|
|
|
|
attribute->class = GetDefaultOpClass(attform->atttypid);
|
|
|
|
if(attribute->class == NULL) {
|
|
|
|
elog(WARN,
|
|
|
|
"Can't find a default operator class for type %d.",
|
|
|
|
attform->atttypid);
|
|
|
|
}
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
tuple = SearchSysCacheTuple(CLANAME,
|
|
|
|
PointerGetDatum(attribute->class),
|
|
|
|
0,0,0);
|
|
|
|
|
|
|
|
if (!HeapTupleIsValid(tuple)) {
|
|
|
|
elog(WARN, "DefineIndex: %s class not found",
|
|
|
|
attribute->class);
|
|
|
|
}
|
|
|
|
*opOidP++ = tuple->t_oid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-08-15 09:42:52 +02:00
|
|
|
static char *
|
|
|
|
GetDefaultOpClass(Oid atttypid)
|
|
|
|
{
|
|
|
|
HeapTuple tuple;
|
|
|
|
|
|
|
|
tuple = SearchSysCacheTuple(CLADEFTYPE,
|
|
|
|
ObjectIdGetDatum(atttypid),
|
|
|
|
0, 0, 0);
|
|
|
|
if(!HeapTupleIsValid(tuple)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nameout(&(((Form_pg_opclass)GETSTRUCT(tuple))->opcname));
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
|
|
|
* RemoveIndex --
|
|
|
|
* Deletes an index.
|
|
|
|
*
|
|
|
|
* Exceptions:
|
|
|
|
* BadArg if name is invalid.
|
1996-08-19 03:53:39 +02:00
|
|
|
* "WARN" if index nonexistent.
|
1996-07-09 08:22:35 +02:00
|
|
|
* ...
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
RemoveIndex(char *name)
|
|
|
|
{
|
|
|
|
HeapTuple tuple;
|
|
|
|
|
|
|
|
tuple = SearchSysCacheTuple(RELNAME,
|
|
|
|
PointerGetDatum(name),
|
|
|
|
0,0,0);
|
|
|
|
|
|
|
|
if (!HeapTupleIsValid(tuple)) {
|
1996-08-19 03:53:39 +02:00
|
|
|
elog(WARN, "index \"%s\" nonexistent", name);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (((Form_pg_class)GETSTRUCT(tuple))->relkind != RELKIND_INDEX) {
|
|
|
|
elog(WARN, "relation \"%s\" is of type \"%c\"",
|
|
|
|
name,
|
|
|
|
((Form_pg_class)GETSTRUCT(tuple))->relkind);
|
|
|
|
}
|
|
|
|
|
|
|
|
index_destroy(tuple->t_oid);
|
|
|
|
}
|