]> granicus.if.org Git - postgresql/blob - src/backend/commands/operatorcmds.c
Second phase of committing Rod Taylor's pg_depend/pg_constraint patch.
[postgresql] / src / backend / commands / operatorcmds.c
1 /*-------------------------------------------------------------------------
2  *
3  * operatorcmds.c
4  *
5  *        Routines for operator manipulation commands
6  *
7  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  *        $Header: /cvsroot/pgsql/src/backend/commands/operatorcmds.c,v 1.5 2002/07/12 18:43:16 tgl Exp $
13  *
14  * DESCRIPTION
15  *        The "DefineFoo" routines take the parse tree and pick out the
16  *        appropriate arguments/flags, passing the results to the
17  *        corresponding "FooDefine" routines (in src/catalog) that do
18  *        the actual catalog-munging.  These routines also verify permission
19  *        of the user to execute the command.
20  *
21  * NOTES
22  *        These things must be defined and committed in the following order:
23  *              "create function":
24  *                              input/output, recv/send procedures
25  *              "create type":
26  *                              type
27  *              "create operator":
28  *                              operators
29  *
30  *              Most of the parse-tree manipulation routines are defined in
31  *              commands/manip.c.
32  *
33  *-------------------------------------------------------------------------
34  */
35 #include "postgres.h"
36
37 #include "access/heapam.h"
38 #include "catalog/catname.h"
39 #include "catalog/dependency.h"
40 #include "catalog/namespace.h"
41 #include "catalog/pg_operator.h"
42 #include "commands/defrem.h"
43 #include "miscadmin.h"
44 #include "parser/parse_oper.h"
45 #include "parser/parse_type.h"
46 #include "utils/acl.h"
47 #include "utils/lsyscache.h"
48 #include "utils/syscache.h"
49
50
51 /*
52  * DefineOperator
53  *              this function extracts all the information from the
54  *              parameter list generated by the parser and then has
55  *              OperatorCreate() do all the actual work.
56  *
57  * 'parameters' is a list of DefElem
58  */
59 void
60 DefineOperator(List *names, List *parameters)
61 {
62         char       *oprName;
63         Oid                     oprNamespace;
64         AclResult       aclresult;
65         uint16          precedence = 0;                 /* operator precedence */
66         bool            canHash = false;                /* operator hashes */
67         bool            canMerge = false;               /* operator merges */
68         bool            isLeftAssociative = true;               /* operator is left
69                                                                                                  * associative */
70         List       *functionName = NIL;         /* function for operator */
71         TypeName   *typeName1 = NULL;           /* first type name */
72         TypeName   *typeName2 = NULL;           /* second type name */
73         Oid                     typeId1 = InvalidOid;   /* types converted to OID */
74         Oid                     typeId2 = InvalidOid;
75         List       *commutatorName = NIL;       /* optional commutator operator
76                                                                                  * name */
77         List       *negatorName = NIL;          /* optional negator operator name */
78         List       *restrictionName = NIL;      /* optional restrict. sel.
79                                                                                  * procedure */
80         List       *joinName = NIL;                     /* optional join sel. procedure */
81         List       *leftSortName = NIL;         /* optional left sort operator */
82         List       *rightSortName = NIL;        /* optional right sort operator */
83         List       *ltCompareName = NIL;        /* optional < compare operator */
84         List       *gtCompareName = NIL;        /* optional > compare operator */
85         List       *pl;
86
87         /* Convert list of names to a name and namespace */
88         oprNamespace = QualifiedNameGetCreationNamespace(names, &oprName);
89
90         /* Check we have creation rights in target namespace */
91         aclresult = pg_namespace_aclcheck(oprNamespace, GetUserId(), ACL_CREATE);
92         if (aclresult != ACLCHECK_OK)
93                 aclcheck_error(aclresult, get_namespace_name(oprNamespace));
94
95         /*
96          * loop over the definition list and extract the information we need.
97          */
98         foreach(pl, parameters)
99         {
100                 DefElem    *defel = (DefElem *) lfirst(pl);
101
102                 if (strcasecmp(defel->defname, "leftarg") == 0)
103                 {
104                         typeName1 = defGetTypeName(defel);
105                         if (typeName1->setof)
106                                 elog(ERROR, "setof type not implemented for leftarg");
107                 }
108                 else if (strcasecmp(defel->defname, "rightarg") == 0)
109                 {
110                         typeName2 = defGetTypeName(defel);
111                         if (typeName2->setof)
112                                 elog(ERROR, "setof type not implemented for rightarg");
113                 }
114                 else if (strcasecmp(defel->defname, "procedure") == 0)
115                         functionName = defGetQualifiedName(defel);
116                 else if (strcasecmp(defel->defname, "precedence") == 0)
117                 {
118                         /* NOT IMPLEMENTED (never worked in v4.2) */
119                         elog(NOTICE, "CREATE OPERATOR: precedence not implemented");
120                 }
121                 else if (strcasecmp(defel->defname, "associativity") == 0)
122                 {
123                         /* NOT IMPLEMENTED (never worked in v4.2) */
124                         elog(NOTICE, "CREATE OPERATOR: associativity not implemented");
125                 }
126                 else if (strcasecmp(defel->defname, "commutator") == 0)
127                         commutatorName = defGetQualifiedName(defel);
128                 else if (strcasecmp(defel->defname, "negator") == 0)
129                         negatorName = defGetQualifiedName(defel);
130                 else if (strcasecmp(defel->defname, "restrict") == 0)
131                         restrictionName = defGetQualifiedName(defel);
132                 else if (strcasecmp(defel->defname, "join") == 0)
133                         joinName = defGetQualifiedName(defel);
134                 else if (strcasecmp(defel->defname, "hashes") == 0)
135                         canHash = TRUE;
136                 else if (strcasecmp(defel->defname, "merges") == 0)
137                         canMerge = TRUE;
138                 else if (strcasecmp(defel->defname, "sort1") == 0)
139                         leftSortName = defGetQualifiedName(defel);
140                 else if (strcasecmp(defel->defname, "sort2") == 0)
141                         rightSortName = defGetQualifiedName(defel);
142                 else if (strcasecmp(defel->defname, "ltcmp") == 0)
143                         ltCompareName = defGetQualifiedName(defel);
144                 else if (strcasecmp(defel->defname, "gtcmp") == 0)
145                         gtCompareName = defGetQualifiedName(defel);
146                 else
147                 {
148                         elog(WARNING, "DefineOperator: attribute \"%s\" not recognized",
149                                  defel->defname);
150                 }
151         }
152
153         /*
154          * make sure we have our required definitions
155          */
156         if (functionName == NIL)
157                 elog(ERROR, "Define: \"procedure\" unspecified");
158
159         /* Transform type names to type OIDs */
160         if (typeName1)
161                 typeId1 = typenameTypeId(typeName1);
162         if (typeName2)
163                 typeId2 = typenameTypeId(typeName2);
164
165         /*
166          * If any of the mergejoin support operators were given, then canMerge
167          * is implicit.  If canMerge is specified or implicit, fill in default
168          * operator names for any missing mergejoin support operators.
169          */
170         if (leftSortName || rightSortName || ltCompareName || gtCompareName)
171                 canMerge = true;
172
173         if (canMerge)
174         {
175                 if (!leftSortName)
176                         leftSortName = makeList1(makeString("<"));
177                 if (!rightSortName)
178                         rightSortName = makeList1(makeString("<"));
179                 if (!ltCompareName)
180                         ltCompareName = makeList1(makeString("<"));
181                 if (!gtCompareName)
182                         gtCompareName = makeList1(makeString(">"));
183         }
184
185         /*
186          * now have OperatorCreate do all the work..
187          */
188         OperatorCreate(oprName,         /* operator name */
189                                    oprNamespace, /* namespace */
190                                    typeId1,             /* left type id */
191                                    typeId2,             /* right type id */
192                                    functionName,        /* function for operator */
193                                    precedence,  /* operator precedence */
194                                    isLeftAssociative,   /* operator is left associative */
195                                    commutatorName,              /* optional commutator operator
196                                                                                  * name */
197                                    negatorName, /* optional negator operator name */
198                                    restrictionName,             /* optional restrict. sel.
199                                                                                  * procedure */
200                                    joinName,    /* optional join sel. procedure name */
201                                    canHash,             /* operator hashes */
202                                    leftSortName,        /* optional left sort operator */
203                                    rightSortName,       /* optional right sort operator */
204                                    ltCompareName,       /* optional < comparison op */
205                                    gtCompareName);      /* optional < comparison op */
206 }
207
208
209 /*
210  * RemoveOperator
211  *              Deletes an operator.
212  */
213 void
214 RemoveOperator(RemoveOperStmt *stmt)
215 {
216         List *operatorName = stmt->opname;
217         TypeName *typeName1 = (TypeName *) lfirst(stmt->args);
218         TypeName *typeName2 = (TypeName *) lsecond(stmt->args);
219         Oid                     operOid;
220         HeapTuple       tup;
221         ObjectAddress object;
222
223         operOid = LookupOperNameTypeNames(operatorName, typeName1, typeName2,
224                                                                           "RemoveOperator");
225
226         tup = SearchSysCache(OPEROID,
227                                                  ObjectIdGetDatum(operOid),
228                                                  0, 0, 0);
229         if (!HeapTupleIsValid(tup))     /* should not happen */
230                 elog(ERROR, "RemoveOperator: failed to find tuple for operator '%s'",
231                          NameListToString(operatorName));
232
233         /* Permission check: must own operator or its namespace */
234         if (!pg_oper_ownercheck(operOid, GetUserId()) &&
235                 !pg_namespace_ownercheck(((Form_pg_operator) GETSTRUCT(tup))->oprnamespace,
236                                                                  GetUserId()))
237                 aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(operatorName));
238
239         ReleaseSysCache(tup);
240
241         /*
242          * Do the deletion
243          */
244         object.classId = get_system_catalog_relid(OperatorRelationName);
245         object.objectId = operOid;
246         object.objectSubId = 0;
247
248         performDeletion(&object, stmt->behavior);
249 }
250
251 /*
252  * Guts of operator deletion.
253  */
254 void
255 RemoveOperatorById(Oid operOid)
256 {
257         Relation        relation;
258         HeapTuple       tup;
259
260         relation = heap_openr(OperatorRelationName, RowExclusiveLock);
261
262         tup = SearchSysCache(OPEROID,
263                                                  ObjectIdGetDatum(operOid),
264                                                  0, 0, 0);
265         if (!HeapTupleIsValid(tup))     /* should not happen */
266                 elog(ERROR, "RemoveOperatorById: failed to find tuple for operator %u",
267                          operOid);
268
269         simple_heap_delete(relation, &tup->t_self);
270
271         ReleaseSysCache(tup);
272
273         heap_close(relation, RowExclusiveLock);
274 }