mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
The contents of command.c, creatinh.c, define.c, remove.c and rename.c
have been divided according to the type of object manipulated - so ALTER TABLE code is in tablecmds.c, aggregate commands in aggregatecmds.c and so on. A few common support routines remain in define.c (prototypes in src/include/commands/defrem.h). No code has been changed except for includes to reflect the new files. The prototypes for aggregatecmds.c, functioncmds.c, operatorcmds.c, and typecmds.c remain in src/include/commands/defrem.h. From John Gray <jgray@azuli.co.uk>
This commit is contained in:
247
src/backend/commands/operatorcmds.c
Normal file
247
src/backend/commands/operatorcmds.c
Normal file
@ -0,0 +1,247 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* operatorcmds.c
|
||||
*
|
||||
* Routines for operator manipulation commands
|
||||
*
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/operatorcmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
* appropriate arguments/flags, passing the results to the
|
||||
* corresponding "FooDefine" routines (in src/catalog) that do
|
||||
* the actual catalog-munging. These routines also verify permission
|
||||
* of the user to execute the command.
|
||||
*
|
||||
* NOTES
|
||||
* These things must be defined and committed in the following order:
|
||||
* "create function":
|
||||
* input/output, recv/send procedures
|
||||
* "create type":
|
||||
* type
|
||||
* "create operator":
|
||||
* operators
|
||||
*
|
||||
* Most of the parse-tree manipulation routines are defined in
|
||||
* commands/manip.c.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/catname.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "commands/comment.h"
|
||||
#include "commands/defrem.h"
|
||||
#include "miscadmin.h"
|
||||
#include "parser/parse_type.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
|
||||
/*
|
||||
* DefineOperator
|
||||
* this function extracts all the information from the
|
||||
* parameter list generated by the parser and then has
|
||||
* OperatorCreate() do all the actual work.
|
||||
*
|
||||
* 'parameters' is a list of DefElem
|
||||
*/
|
||||
void
|
||||
DefineOperator(List *names, List *parameters)
|
||||
{
|
||||
char *oprName;
|
||||
Oid oprNamespace;
|
||||
uint16 precedence = 0; /* operator precedence */
|
||||
bool canHash = false; /* operator hashes */
|
||||
bool isLeftAssociative = true; /* operator is left
|
||||
* associative */
|
||||
char *functionName = NULL; /* function for operator */
|
||||
TypeName *typeName1 = NULL; /* first type name */
|
||||
TypeName *typeName2 = NULL; /* second type name */
|
||||
Oid typeId1 = InvalidOid; /* types converted to OID */
|
||||
Oid typeId2 = InvalidOid;
|
||||
char *commutatorName = NULL; /* optional commutator operator
|
||||
* name */
|
||||
char *negatorName = NULL; /* optional negator operator name */
|
||||
char *restrictionName = NULL; /* optional restrict. sel.
|
||||
* procedure */
|
||||
char *joinName = NULL; /* optional join sel. procedure name */
|
||||
char *sortName1 = NULL; /* optional first sort operator */
|
||||
char *sortName2 = NULL; /* optional second sort operator */
|
||||
List *pl;
|
||||
|
||||
/* Convert list of names to a name and namespace */
|
||||
oprNamespace = QualifiedNameGetCreationNamespace(names, &oprName);
|
||||
|
||||
/*
|
||||
* loop over the definition list and extract the information we need.
|
||||
*/
|
||||
foreach(pl, parameters)
|
||||
{
|
||||
DefElem *defel = (DefElem *) lfirst(pl);
|
||||
|
||||
if (strcasecmp(defel->defname, "leftarg") == 0)
|
||||
{
|
||||
typeName1 = defGetTypeName(defel);
|
||||
if (typeName1->setof)
|
||||
elog(ERROR, "setof type not implemented for leftarg");
|
||||
}
|
||||
else if (strcasecmp(defel->defname, "rightarg") == 0)
|
||||
{
|
||||
typeName2 = defGetTypeName(defel);
|
||||
if (typeName2->setof)
|
||||
elog(ERROR, "setof type not implemented for rightarg");
|
||||
}
|
||||
else if (strcasecmp(defel->defname, "procedure") == 0)
|
||||
functionName = defGetString(defel);
|
||||
else if (strcasecmp(defel->defname, "precedence") == 0)
|
||||
{
|
||||
/* NOT IMPLEMENTED (never worked in v4.2) */
|
||||
elog(NOTICE, "CREATE OPERATOR: precedence not implemented");
|
||||
}
|
||||
else if (strcasecmp(defel->defname, "associativity") == 0)
|
||||
{
|
||||
/* NOT IMPLEMENTED (never worked in v4.2) */
|
||||
elog(NOTICE, "CREATE OPERATOR: associativity not implemented");
|
||||
}
|
||||
else if (strcasecmp(defel->defname, "commutator") == 0)
|
||||
commutatorName = defGetString(defel);
|
||||
else if (strcasecmp(defel->defname, "negator") == 0)
|
||||
negatorName = defGetString(defel);
|
||||
else if (strcasecmp(defel->defname, "restrict") == 0)
|
||||
restrictionName = defGetString(defel);
|
||||
else if (strcasecmp(defel->defname, "join") == 0)
|
||||
joinName = defGetString(defel);
|
||||
else if (strcasecmp(defel->defname, "hashes") == 0)
|
||||
canHash = TRUE;
|
||||
else if (strcasecmp(defel->defname, "sort1") == 0)
|
||||
sortName1 = defGetString(defel);
|
||||
else if (strcasecmp(defel->defname, "sort2") == 0)
|
||||
sortName2 = defGetString(defel);
|
||||
else
|
||||
{
|
||||
elog(WARNING, "DefineOperator: attribute \"%s\" not recognized",
|
||||
defel->defname);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* make sure we have our required definitions
|
||||
*/
|
||||
if (functionName == NULL)
|
||||
elog(ERROR, "Define: \"procedure\" unspecified");
|
||||
|
||||
/* Transform type names to type OIDs */
|
||||
if (typeName1)
|
||||
typeId1 = typenameTypeId(typeName1);
|
||||
if (typeName2)
|
||||
typeId2 = typenameTypeId(typeName2);
|
||||
|
||||
/*
|
||||
* now have OperatorCreate do all the work..
|
||||
*/
|
||||
OperatorCreate(oprName, /* operator name */
|
||||
typeId1, /* left type id */
|
||||
typeId2, /* right type id */
|
||||
functionName, /* function for operator */
|
||||
precedence, /* operator precedence */
|
||||
isLeftAssociative, /* operator is left associative */
|
||||
commutatorName, /* optional commutator operator
|
||||
* name */
|
||||
negatorName, /* optional negator operator name */
|
||||
restrictionName, /* optional restrict. sel.
|
||||
* procedure */
|
||||
joinName, /* optional join sel. procedure name */
|
||||
canHash, /* operator hashes */
|
||||
sortName1, /* optional first sort operator */
|
||||
sortName2); /* optional second sort operator */
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* RemoveOperator
|
||||
* Deletes an operator.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if name is invalid.
|
||||
* BadArg if type1 is invalid.
|
||||
* "ERROR" if operator nonexistent.
|
||||
* ...
|
||||
*/
|
||||
void
|
||||
RemoveOperator(char *operatorName, /* operator name */
|
||||
TypeName *typeName1, /* left argument type name */
|
||||
TypeName *typeName2) /* right argument type name */
|
||||
{
|
||||
Relation relation;
|
||||
HeapTuple tup;
|
||||
Oid typeId1 = InvalidOid;
|
||||
Oid typeId2 = InvalidOid;
|
||||
char oprtype;
|
||||
|
||||
if (typeName1)
|
||||
typeId1 = typenameTypeId(typeName1);
|
||||
|
||||
if (typeName2)
|
||||
typeId2 = typenameTypeId(typeName2);
|
||||
|
||||
if (OidIsValid(typeId1) && OidIsValid(typeId2))
|
||||
oprtype = 'b';
|
||||
else if (OidIsValid(typeId1))
|
||||
oprtype = 'r';
|
||||
else
|
||||
oprtype = 'l';
|
||||
|
||||
relation = heap_openr(OperatorRelationName, RowExclusiveLock);
|
||||
|
||||
tup = SearchSysCacheCopy(OPERNAME,
|
||||
PointerGetDatum(operatorName),
|
||||
ObjectIdGetDatum(typeId1),
|
||||
ObjectIdGetDatum(typeId2),
|
||||
CharGetDatum(oprtype));
|
||||
|
||||
if (HeapTupleIsValid(tup))
|
||||
{
|
||||
if (!pg_oper_ownercheck(tup->t_data->t_oid, GetUserId()))
|
||||
elog(ERROR, "RemoveOperator: operator '%s': permission denied",
|
||||
operatorName);
|
||||
|
||||
/* Delete any comments associated with this operator */
|
||||
DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
|
||||
|
||||
simple_heap_delete(relation, &tup->t_self);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (OidIsValid(typeId1) && OidIsValid(typeId2))
|
||||
{
|
||||
elog(ERROR, "RemoveOperator: binary operator '%s' taking '%s' and '%s' does not exist",
|
||||
operatorName,
|
||||
TypeNameToString(typeName1),
|
||||
TypeNameToString(typeName2));
|
||||
}
|
||||
else if (OidIsValid(typeId1))
|
||||
{
|
||||
elog(ERROR, "RemoveOperator: right unary operator '%s' taking '%s' does not exist",
|
||||
operatorName,
|
||||
TypeNameToString(typeName1));
|
||||
}
|
||||
else
|
||||
{
|
||||
elog(ERROR, "RemoveOperator: left unary operator '%s' taking '%s' does not exist",
|
||||
operatorName,
|
||||
TypeNameToString(typeName2));
|
||||
}
|
||||
}
|
||||
heap_freetuple(tup);
|
||||
heap_close(relation, RowExclusiveLock);
|
||||
}
|
Reference in New Issue
Block a user