]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/regproc.c
regprocin should accept '-' signifying InvalidOid, for
[postgresql] / src / backend / utils / adt / regproc.c
1  /*-------------------------------------------------------------------------
2  *
3  * regproc.c
4  *        Functions for the built-in type "RegProcedure".
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.35 1999/02/15 16:29:32 tgl Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include <string.h>
15 #include "postgres.h"
16 #include "miscadmin.h"
17 #include "access/heapam.h"
18 #include "access/genam.h"
19 #include "access/itup.h"
20 #include "access/relscan.h"
21 #include "storage/bufmgr.h"
22 #include "fmgr.h"
23 #include "utils/palloc.h"
24 #include "utils/syscache.h"
25
26 #include "catalog/catname.h"
27 #include "catalog/indexing.h"
28 #include "catalog/pg_proc.h"
29 #include "catalog/pg_type.h"
30 #include "utils/builtins.h"             /* where function declarations go */
31
32 /*****************************************************************************
33  *       USER I/O ROUTINES                                                                                                               *
34  *****************************************************************************/
35
36 /*
37  *              regprocin               - converts "proname" or "proid" to proid
38  *
39  *              proid of '-' signifies unknown, for consistency with regprocout
40  */
41 int32
42 regprocin(char *pro_name_or_oid)
43 {
44         HeapTuple               proctup = NULL;
45         HeapTupleData   tuple;
46         RegProcedure    result = InvalidOid;
47
48         if (pro_name_or_oid == NULL)
49                 return InvalidOid;
50         if (pro_name_or_oid[0] == '-' && pro_name_or_oid[1] == '\0')
51                 return InvalidOid;
52
53         if (!IsBootstrapProcessingMode())
54         {
55                 /*
56                  * we need to use the oid because there can be multiple entries
57                  * with the same name.  We accept int4eq_1323 and 1323.
58                  */
59                 if (pro_name_or_oid[0] >= '0' &&
60                         pro_name_or_oid[0] <= '9')
61                 {
62                         proctup = SearchSysCacheTuple(PROOID,
63                                                                 ObjectIdGetDatum(oidin(pro_name_or_oid)),
64                                                                                   0, 0, 0);
65                         if (HeapTupleIsValid(proctup))
66                                 result = (RegProcedure) proctup->t_data->t_oid;
67                         else
68                                 elog(ERROR, "No procedure with oid %s", pro_name_or_oid);
69                 }
70                 else
71                 {
72                         Relation        hdesc;
73                         Relation        idesc;
74                         IndexScanDesc sd;
75                         ScanKeyData skey[1];
76                         RetrieveIndexResult indexRes;
77                         Buffer          buffer;
78                         int                     matches = 0;
79                 
80                         ScanKeyEntryInitialize(&skey[0],
81                                                                    (bits16) 0x0,
82                                                                    (AttrNumber) 1,
83                                                                    (RegProcedure) F_NAMEEQ,
84                                                                    PointerGetDatum(pro_name_or_oid));
85                 
86                         hdesc = heap_openr(ProcedureRelationName);
87                         idesc = index_openr(ProcedureNameIndex);
88                 
89                         sd = index_beginscan(idesc, false, 1, skey);
90                         while ((indexRes = index_getnext(sd, ForwardScanDirection)))
91                         {
92                                 tuple.t_self = indexRes->heap_iptr;
93                                 heap_fetch(hdesc, SnapshotNow,
94                                                                         &tuple,
95                                                                         &buffer);
96                                 pfree(indexRes);
97                                 if (tuple.t_data != NULL)
98                                 {
99                                         result = (RegProcedure) tuple.t_data->t_oid;
100                                         ReleaseBuffer(buffer);
101
102                                         if (++matches > 1)
103                                                 break;
104                                 }
105                         }
106
107                         index_endscan(sd);
108                         pfree(sd);
109                         index_close(idesc);
110
111                         if (matches > 1)
112                                 elog(ERROR, "There is more than one procedure named %s.\n\tSupply the pg_proc oid inside single quotes.", pro_name_or_oid);
113                         else if (matches == 0)
114                                 elog(ERROR, "No procedure with name %s", pro_name_or_oid);
115                 }
116         }
117         else
118         {
119                 Relation        proc;
120                 HeapScanDesc procscan;
121                 ScanKeyData key;
122                 bool            isnull;
123
124                 proc = heap_openr(ProcedureRelationName);
125                 if (!RelationIsValid(proc))
126                 {
127                         elog(ERROR, "regprocin: could not open %s",
128                                  ProcedureRelationName);
129                         return 0;
130                 }
131                 ScanKeyEntryInitialize(&key,
132                                                            (bits16) 0,
133                                                            (AttrNumber) 1,
134                                                            (RegProcedure) F_NAMEEQ,
135                                                            (Datum) pro_name_or_oid);
136
137                 procscan = heap_beginscan(proc, 0, SnapshotNow, 1, &key);
138                 if (!HeapScanIsValid(procscan))
139                 {
140                         heap_close(proc);
141                         elog(ERROR, "regprocin: could not being scan of %s",
142                                  ProcedureRelationName);
143                         return 0;
144                 }
145                 proctup = heap_getnext(procscan, 0);
146                 if (HeapTupleIsValid(proctup))
147                 {
148                         result = (RegProcedure) heap_getattr(proctup,
149                                                                                                  ObjectIdAttributeNumber,
150                                                                                                  RelationGetDescr(proc),
151                                                                                                  &isnull);
152                         if (isnull)
153                                 elog(FATAL, "regprocin: null procedure %s", pro_name_or_oid);
154                 }
155                 else
156                         result = (RegProcedure) 0;
157
158                 heap_endscan(procscan);
159                 heap_close(proc);
160         }
161
162         return (int32) result;
163 }
164
165 /*
166  *              regprocout              - converts proid to "pro_name"
167  */
168 char *
169 regprocout(RegProcedure proid)
170 {
171         HeapTuple       proctup;
172         char       *result;
173
174         result = (char *) palloc(NAMEDATALEN);
175
176         if (!IsBootstrapProcessingMode())
177         {
178                 proctup = SearchSysCacheTuple(PROOID,
179                                                                           ObjectIdGetDatum(proid),
180                                                                           0, 0, 0);
181
182                 if (HeapTupleIsValid(proctup))
183                 {
184                         char       *s;
185
186                         s = ((Form_pg_proc) GETSTRUCT(proctup))->proname.data;
187                         StrNCpy(result, s, NAMEDATALEN);
188                 }
189                 else
190                 {
191                         result[0] = '-';
192                         result[1] = '\0';
193                 }
194         }
195         else
196         {
197                 Relation        proc;
198                 HeapScanDesc procscan;
199                 ScanKeyData key;
200
201                 proc = heap_openr(ProcedureRelationName);
202                 if (!RelationIsValid(proc))
203                 {
204                         elog(ERROR, "regprocout: could not open %s", ProcedureRelationName);
205                         return 0;
206                 }
207                 ScanKeyEntryInitialize(&key,
208                                                            (bits16) 0,
209                                                            (AttrNumber) ObjectIdAttributeNumber,
210                                                            (RegProcedure) F_INT4EQ,
211                                                            (Datum) proid);
212
213                 procscan = heap_beginscan(proc, 0, SnapshotNow, 1, &key);
214                 if (!HeapScanIsValid(procscan))
215                 {
216                         heap_close(proc);
217                         elog(ERROR, "regprocout: could not being scan of %s",
218                                  ProcedureRelationName);
219                         return 0;
220                 }
221                 proctup = heap_getnext(procscan, 0);
222                 if (HeapTupleIsValid(proctup))
223                 {
224                         char       *s;
225                         bool            isnull;
226
227                         s = (char *) heap_getattr(proctup, 1,
228                                                                           RelationGetDescr(proc), &isnull);
229                         if (!isnull)
230                                 StrNCpy(result, s, NAMEDATALEN);
231                         else
232                                 elog(FATAL, "regprocout: null procedure %d", proid);
233                 }
234                 else
235                 {
236                         result[0] = '-';
237                         result[1] = '\0';
238                 }
239                 heap_endscan(procscan);
240                 heap_close(proc);
241                 return result;
242         }
243
244         return result;
245 }
246
247 /*
248  *              int8typeout                     - converts int8 type oids to "typname" list
249  */
250 text *
251 oid8types(Oid *oidArray)
252 {
253         HeapTuple       typetup;
254         text       *result;
255         int                     num;
256         Oid                *sp;
257
258         if (oidArray == NULL)
259         {
260                 result = (text *) palloc(VARHDRSZ);
261                 VARSIZE(result) = 0;
262                 return result;
263         }
264
265         result = (text *) palloc(NAMEDATALEN * 8 + 8 + VARHDRSZ);
266         *VARDATA(result) = '\0';
267
268         sp = oidArray;
269         for (num = 8; num != 0; num--, sp++)
270         {
271                 if (*sp != InvalidOid)
272                 {
273                         typetup = SearchSysCacheTuple(TYPOID,
274                                                                                   ObjectIdGetDatum(*sp),
275                                                                                   0, 0, 0);
276                         if (HeapTupleIsValid(typetup))
277                         {
278                                 char       *s;
279
280                                 s = ((Form_pg_type) GETSTRUCT(typetup))->typname.data;
281                                 StrNCpy(VARDATA(result) + strlen(VARDATA(result)), s,
282                                                 NAMEDATALEN);
283                                 strcat(VARDATA(result), " ");
284                         }
285                 }
286         }
287         VARSIZE(result) = strlen(VARDATA(result)) + VARHDRSZ;
288         return result;
289 }
290
291
292 /*****************************************************************************
293  *       PUBLIC ROUTINES                                                                                                                 *
294  *****************************************************************************/
295
296 /* regproctooid()
297  * Lowercase version of RegprocToOid() to allow case-insensitive SQL.
298  * Define RegprocToOid() as a macro in builtins.h.
299  * Referenced in pg_proc.h. - tgl 97/04/26
300  */
301 Oid
302 regproctooid(RegProcedure rp)
303 {
304         return (Oid) rp;
305 }
306
307 /* (see int.c for comparison/operation routines) */
308
309
310 /* ========== PRIVATE ROUTINES ========== */