]> granicus.if.org Git - postgresql/blob - src/backend/commands/operatorcmds.c
Remove unused system table columns:
[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.6 2002/07/24 19:11:09 petere 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, get_namespace_name(oprNamespace));
91
92         /*
93          * loop over the definition list and extract the information we need.
94          */
95         foreach(pl, parameters)
96         {
97                 DefElem    *defel = (DefElem *) lfirst(pl);
98
99                 if (strcasecmp(defel->defname, "leftarg") == 0)
100                 {
101                         typeName1 = defGetTypeName(defel);
102                         if (typeName1->setof)
103                                 elog(ERROR, "setof type not implemented for leftarg");
104                 }
105                 else if (strcasecmp(defel->defname, "rightarg") == 0)
106                 {
107                         typeName2 = defGetTypeName(defel);
108                         if (typeName2->setof)
109                                 elog(ERROR, "setof type not implemented for rightarg");
110                 }
111                 else if (strcasecmp(defel->defname, "procedure") == 0)
112                         functionName = defGetQualifiedName(defel);
113                 else if (strcasecmp(defel->defname, "commutator") == 0)
114                         commutatorName = defGetQualifiedName(defel);
115                 else if (strcasecmp(defel->defname, "negator") == 0)
116                         negatorName = defGetQualifiedName(defel);
117                 else if (strcasecmp(defel->defname, "restrict") == 0)
118                         restrictionName = defGetQualifiedName(defel);
119                 else if (strcasecmp(defel->defname, "join") == 0)
120                         joinName = defGetQualifiedName(defel);
121                 else if (strcasecmp(defel->defname, "hashes") == 0)
122                         canHash = TRUE;
123                 else if (strcasecmp(defel->defname, "merges") == 0)
124                         canMerge = TRUE;
125                 else if (strcasecmp(defel->defname, "sort1") == 0)
126                         leftSortName = defGetQualifiedName(defel);
127                 else if (strcasecmp(defel->defname, "sort2") == 0)
128                         rightSortName = defGetQualifiedName(defel);
129                 else if (strcasecmp(defel->defname, "ltcmp") == 0)
130                         ltCompareName = defGetQualifiedName(defel);
131                 else if (strcasecmp(defel->defname, "gtcmp") == 0)
132                         gtCompareName = defGetQualifiedName(defel);
133                 else
134                 {
135                         elog(WARNING, "DefineOperator: attribute \"%s\" not recognized",
136                                  defel->defname);
137                 }
138         }
139
140         /*
141          * make sure we have our required definitions
142          */
143         if (functionName == NIL)
144                 elog(ERROR, "Define: \"procedure\" unspecified");
145
146         /* Transform type names to type OIDs */
147         if (typeName1)
148                 typeId1 = typenameTypeId(typeName1);
149         if (typeName2)
150                 typeId2 = typenameTypeId(typeName2);
151
152         /*
153          * If any of the mergejoin support operators were given, then canMerge
154          * is implicit.  If canMerge is specified or implicit, fill in default
155          * operator names for any missing mergejoin support operators.
156          */
157         if (leftSortName || rightSortName || ltCompareName || gtCompareName)
158                 canMerge = true;
159
160         if (canMerge)
161         {
162                 if (!leftSortName)
163                         leftSortName = makeList1(makeString("<"));
164                 if (!rightSortName)
165                         rightSortName = makeList1(makeString("<"));
166                 if (!ltCompareName)
167                         ltCompareName = makeList1(makeString("<"));
168                 if (!gtCompareName)
169                         gtCompareName = makeList1(makeString(">"));
170         }
171
172         /*
173          * now have OperatorCreate do all the work..
174          */
175         OperatorCreate(oprName,         /* operator name */
176                                    oprNamespace, /* namespace */
177                                    typeId1,             /* left type id */
178                                    typeId2,             /* right type id */
179                                    functionName,        /* function for operator */
180                                    commutatorName,              /* optional commutator operator
181                                                                                  * name */
182                                    negatorName, /* optional negator operator name */
183                                    restrictionName,             /* optional restrict. sel.
184                                                                                  * procedure */
185                                    joinName,    /* optional join sel. procedure name */
186                                    canHash,             /* operator hashes */
187                                    leftSortName,        /* optional left sort operator */
188                                    rightSortName,       /* optional right sort operator */
189                                    ltCompareName,       /* optional < comparison op */
190                                    gtCompareName);      /* optional < comparison op */
191 }
192
193
194 /*
195  * RemoveOperator
196  *              Deletes an operator.
197  */
198 void
199 RemoveOperator(RemoveOperStmt *stmt)
200 {
201         List *operatorName = stmt->opname;
202         TypeName *typeName1 = (TypeName *) lfirst(stmt->args);
203         TypeName *typeName2 = (TypeName *) lsecond(stmt->args);
204         Oid                     operOid;
205         HeapTuple       tup;
206         ObjectAddress object;
207
208         operOid = LookupOperNameTypeNames(operatorName, typeName1, typeName2,
209                                                                           "RemoveOperator");
210
211         tup = SearchSysCache(OPEROID,
212                                                  ObjectIdGetDatum(operOid),
213                                                  0, 0, 0);
214         if (!HeapTupleIsValid(tup))     /* should not happen */
215                 elog(ERROR, "RemoveOperator: failed to find tuple for operator '%s'",
216                          NameListToString(operatorName));
217
218         /* Permission check: must own operator or its namespace */
219         if (!pg_oper_ownercheck(operOid, GetUserId()) &&
220                 !pg_namespace_ownercheck(((Form_pg_operator) GETSTRUCT(tup))->oprnamespace,
221                                                                  GetUserId()))
222                 aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(operatorName));
223
224         ReleaseSysCache(tup);
225
226         /*
227          * Do the deletion
228          */
229         object.classId = get_system_catalog_relid(OperatorRelationName);
230         object.objectId = operOid;
231         object.objectSubId = 0;
232
233         performDeletion(&object, stmt->behavior);
234 }
235
236 /*
237  * Guts of operator deletion.
238  */
239 void
240 RemoveOperatorById(Oid operOid)
241 {
242         Relation        relation;
243         HeapTuple       tup;
244
245         relation = heap_openr(OperatorRelationName, RowExclusiveLock);
246
247         tup = SearchSysCache(OPEROID,
248                                                  ObjectIdGetDatum(operOid),
249                                                  0, 0, 0);
250         if (!HeapTupleIsValid(tup))     /* should not happen */
251                 elog(ERROR, "RemoveOperatorById: failed to find tuple for operator %u",
252                          operOid);
253
254         simple_heap_delete(relation, &tup->t_self);
255
256         ReleaseSysCache(tup);
257
258         heap_close(relation, RowExclusiveLock);
259 }