]> granicus.if.org Git - postgresql/blob - src/backend/commands/operatorcmds.c
Update copyrights to 2003.
[postgresql] / src / backend / commands / operatorcmds.c
1 /*-------------------------------------------------------------------------
2  *
3  * operatorcmds.c
4  *
5  *        Routines for operator manipulation commands
6  *
7  * Portions Copyright (c) 1996-2003, 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.12 2003/08/04 02:39:58 momjian 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         bool            canHash = false;        /* operator hashes */
66         bool            canMerge = false;               /* operator merges */
67         List       *functionName = NIL;         /* function for operator */
68         TypeName   *typeName1 = NULL;           /* first type name */
69         TypeName   *typeName2 = NULL;           /* second type name */
70         Oid                     typeId1 = InvalidOid;   /* types converted to OID */
71         Oid                     typeId2 = InvalidOid;
72         List       *commutatorName = NIL;       /* optional commutator operator
73                                                                                  * name */
74         List       *negatorName = NIL;          /* optional negator operator name */
75         List       *restrictionName = NIL;      /* optional restrict. sel.
76                                                                                  * procedure */
77         List       *joinName = NIL; /* optional join sel. procedure */
78         List       *leftSortName = NIL;         /* optional left sort operator */
79         List       *rightSortName = NIL;        /* optional right sort operator */
80         List       *ltCompareName = NIL;        /* optional < compare operator */
81         List       *gtCompareName = NIL;        /* optional > compare operator */
82         List       *pl;
83
84         /* Convert list of names to a name and namespace */
85         oprNamespace = QualifiedNameGetCreationNamespace(names, &oprName);
86
87         /* Check we have creation rights in target namespace */
88         aclresult = pg_namespace_aclcheck(oprNamespace, GetUserId(), ACL_CREATE);
89         if (aclresult != ACLCHECK_OK)
90                 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
91                                            get_namespace_name(oprNamespace));
92
93         /*
94          * loop over the definition list and extract the information we need.
95          */
96         foreach(pl, parameters)
97         {
98                 DefElem    *defel = (DefElem *) lfirst(pl);
99
100                 if (strcasecmp(defel->defname, "leftarg") == 0)
101                 {
102                         typeName1 = defGetTypeName(defel);
103                         if (typeName1->setof)
104                                 ereport(ERROR,
105                                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
106                                 errmsg("setof type not allowed for operator argument")));
107                 }
108                 else if (strcasecmp(defel->defname, "rightarg") == 0)
109                 {
110                         typeName2 = defGetTypeName(defel);
111                         if (typeName2->setof)
112                                 ereport(ERROR,
113                                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
114                                 errmsg("setof type not allowed for operator argument")));
115                 }
116                 else if (strcasecmp(defel->defname, "procedure") == 0)
117                         functionName = defGetQualifiedName(defel);
118                 else if (strcasecmp(defel->defname, "commutator") == 0)
119                         commutatorName = defGetQualifiedName(defel);
120                 else if (strcasecmp(defel->defname, "negator") == 0)
121                         negatorName = defGetQualifiedName(defel);
122                 else if (strcasecmp(defel->defname, "restrict") == 0)
123                         restrictionName = defGetQualifiedName(defel);
124                 else if (strcasecmp(defel->defname, "join") == 0)
125                         joinName = defGetQualifiedName(defel);
126                 else if (strcasecmp(defel->defname, "hashes") == 0)
127                         canHash = TRUE;
128                 else if (strcasecmp(defel->defname, "merges") == 0)
129                         canMerge = TRUE;
130                 else if (strcasecmp(defel->defname, "sort1") == 0)
131                         leftSortName = defGetQualifiedName(defel);
132                 else if (strcasecmp(defel->defname, "sort2") == 0)
133                         rightSortName = defGetQualifiedName(defel);
134                 else if (strcasecmp(defel->defname, "ltcmp") == 0)
135                         ltCompareName = defGetQualifiedName(defel);
136                 else if (strcasecmp(defel->defname, "gtcmp") == 0)
137                         gtCompareName = defGetQualifiedName(defel);
138                 else
139                         ereport(WARNING,
140                                         (errcode(ERRCODE_SYNTAX_ERROR),
141                                          errmsg("operator attribute \"%s\" not recognized",
142                                                         defel->defname)));
143         }
144
145         /*
146          * make sure we have our required definitions
147          */
148         if (functionName == NIL)
149                 ereport(ERROR,
150                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
151                                  errmsg("operator procedure must be specified")));
152
153         /* Transform type names to type OIDs */
154         if (typeName1)
155                 typeId1 = typenameTypeId(typeName1);
156         if (typeName2)
157                 typeId2 = typenameTypeId(typeName2);
158
159         /*
160          * If any of the mergejoin support operators were given, then canMerge
161          * is implicit.  If canMerge is specified or implicit, fill in default
162          * operator names for any missing mergejoin support operators.
163          */
164         if (leftSortName || rightSortName || ltCompareName || gtCompareName)
165                 canMerge = true;
166
167         if (canMerge)
168         {
169                 if (!leftSortName)
170                         leftSortName = makeList1(makeString("<"));
171                 if (!rightSortName)
172                         rightSortName = makeList1(makeString("<"));
173                 if (!ltCompareName)
174                         ltCompareName = makeList1(makeString("<"));
175                 if (!gtCompareName)
176                         gtCompareName = makeList1(makeString(">"));
177         }
178
179         /*
180          * now have OperatorCreate do all the work..
181          */
182         OperatorCreate(oprName,         /* operator name */
183                                    oprNamespace,        /* namespace */
184                                    typeId1,             /* left type id */
185                                    typeId2,             /* right type id */
186                                    functionName,        /* function for operator */
187                                    commutatorName,              /* optional commutator operator
188                                                                                  * name */
189                                    negatorName, /* optional negator operator name */
190                                    restrictionName,             /* optional restrict. sel.
191                                                                                  * procedure */
192                                    joinName,    /* optional join sel. procedure name */
193                                    canHash,             /* operator hashes */
194                                    leftSortName,        /* optional left sort operator */
195                                    rightSortName,               /* optional right sort operator */
196                                    ltCompareName,               /* optional < comparison op */
197                                    gtCompareName);              /* optional < comparison op */
198 }
199
200
201 /*
202  * RemoveOperator
203  *              Deletes an operator.
204  */
205 void
206 RemoveOperator(RemoveOperStmt *stmt)
207 {
208         List       *operatorName = stmt->opname;
209         TypeName   *typeName1 = (TypeName *) lfirst(stmt->args);
210         TypeName   *typeName2 = (TypeName *) lsecond(stmt->args);
211         Oid                     operOid;
212         HeapTuple       tup;
213         ObjectAddress object;
214
215         operOid = LookupOperNameTypeNames(operatorName, typeName1, typeName2,
216                                                                           false);
217
218         tup = SearchSysCache(OPEROID,
219                                                  ObjectIdGetDatum(operOid),
220                                                  0, 0, 0);
221         if (!HeapTupleIsValid(tup)) /* should not happen */
222                 elog(ERROR, "cache lookup failed for operator %u", operOid);
223
224         /* Permission check: must own operator or its namespace */
225         if (!pg_oper_ownercheck(operOid, GetUserId()) &&
226                 !pg_namespace_ownercheck(((Form_pg_operator) GETSTRUCT(tup))->oprnamespace,
227                                                                  GetUserId()))
228                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
229                                            NameListToString(operatorName));
230
231         ReleaseSysCache(tup);
232
233         /*
234          * Do the deletion
235          */
236         object.classId = get_system_catalog_relid(OperatorRelationName);
237         object.objectId = operOid;
238         object.objectSubId = 0;
239
240         performDeletion(&object, stmt->behavior);
241 }
242
243 /*
244  * Guts of operator deletion.
245  */
246 void
247 RemoveOperatorById(Oid operOid)
248 {
249         Relation        relation;
250         HeapTuple       tup;
251
252         relation = heap_openr(OperatorRelationName, RowExclusiveLock);
253
254         tup = SearchSysCache(OPEROID,
255                                                  ObjectIdGetDatum(operOid),
256                                                  0, 0, 0);
257         if (!HeapTupleIsValid(tup)) /* should not happen */
258                 elog(ERROR, "cache lookup failed for operator %u", operOid);
259
260         simple_heap_delete(relation, &tup->t_self);
261
262         ReleaseSysCache(tup);
263
264         heap_close(relation, RowExclusiveLock);
265 }