]> granicus.if.org Git - postgresql/blob - src/backend/commands/proclang.c
Privileges on functions and procedural languages
[postgresql] / src / backend / commands / proclang.c
1 /*-------------------------------------------------------------------------
2  *
3  * proclang.c
4  *        PostgreSQL PROCEDURAL LANGUAGE support code.
5  *
6  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.29 2002/02/18 23:11:11 petere Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15
16 #include <ctype.h>
17
18 #include "access/heapam.h"
19 #include "catalog/catname.h"
20 #include "catalog/indexing.h"
21 #include "catalog/pg_language.h"
22 #include "catalog/pg_proc.h"
23 #include "commands/proclang.h"
24 #include "fmgr.h"
25 #include "miscadmin.h"
26 #include "utils/builtins.h"
27 #include "utils/syscache.h"
28
29
30 /*
31  * Translate the input language name to lower case.
32  */
33 static void
34 case_translate_language_name(const char *input, char *output)
35 {
36         int                     i;
37
38         for (i = 0; i < NAMEDATALEN && input[i]; ++i)
39                 output[i] = tolower((unsigned char) input[i]);
40
41         output[i] = '\0';
42 }
43
44
45 /* ---------------------------------------------------------------------
46  * CREATE PROCEDURAL LANGUAGE
47  * ---------------------------------------------------------------------
48  */
49 void
50 CreateProceduralLanguage(CreatePLangStmt *stmt)
51 {
52         char            languageName[NAMEDATALEN];
53         HeapTuple       procTup;
54
55         Oid                     typev[FUNC_MAX_ARGS];
56         char            nulls[Natts_pg_language];
57         Datum           values[Natts_pg_language];
58         Relation        rel;
59         HeapTuple       tup;
60         TupleDesc       tupDesc;
61
62         int                     i;
63
64         /*
65          * Check permission
66          */
67         if (!superuser())
68                 elog(ERROR, "Only users with Postgres superuser privilege are "
69                          "permitted to create procedural languages");
70
71         /*
72          * Translate the language name and check that this language doesn't
73          * already exist
74          */
75         case_translate_language_name(stmt->plname, languageName);
76
77         if (SearchSysCacheExists(LANGNAME,
78                                                          PointerGetDatum(languageName),
79                                                          0, 0, 0))
80                 elog(ERROR, "Language %s already exists", languageName);
81
82         /*
83          * Lookup the PL handler function and check that it is of return type
84          * Opaque
85          */
86         memset(typev, 0, sizeof(typev));
87         procTup = SearchSysCache(PROCNAME,
88                                                          PointerGetDatum(stmt->plhandler),
89                                                          Int32GetDatum(0),
90                                                          PointerGetDatum(typev),
91                                                          0);
92         if (!HeapTupleIsValid(procTup))
93                 elog(ERROR, "PL handler function %s() doesn't exist",
94                          stmt->plhandler);
95         if (((Form_pg_proc) GETSTRUCT(procTup))->prorettype != InvalidOid)
96                 elog(ERROR, "PL handler function %s() isn't of return type Opaque",
97                          stmt->plhandler);
98
99         /*
100          * Insert the new language into pg_language
101          */
102         for (i = 0; i < Natts_pg_language; i++)
103         {
104                 nulls[i] = ' ';
105                 values[i] = (Datum) NULL;
106         }
107
108         i = 0;
109         values[i++] = PointerGetDatum(languageName);
110         values[i++] = BoolGetDatum(true);       /* lanispl */
111         values[i++] = BoolGetDatum(stmt->pltrusted);
112         values[i++] = ObjectIdGetDatum(procTup->t_data->t_oid);
113         values[i++] = DirectFunctionCall1(textin,
114                                                                           CStringGetDatum(stmt->plcompiler));
115         nulls[i] = 'n';                         /* lanacl */
116
117         ReleaseSysCache(procTup);
118
119         rel = heap_openr(LanguageRelationName, RowExclusiveLock);
120
121         tupDesc = rel->rd_att;
122         tup = heap_formtuple(tupDesc, values, nulls);
123
124         heap_insert(rel, tup);
125
126         if (RelationGetForm(rel)->relhasindex)
127         {
128                 Relation        idescs[Num_pg_language_indices];
129
130                 CatalogOpenIndices(Num_pg_language_indices, Name_pg_language_indices, idescs);
131                 CatalogIndexInsert(idescs, Num_pg_language_indices, rel, tup);
132                 CatalogCloseIndices(Num_pg_language_indices, idescs);
133         }
134
135         heap_close(rel, RowExclusiveLock);
136 }
137
138
139 /* ---------------------------------------------------------------------
140  * DROP PROCEDURAL LANGUAGE
141  * ---------------------------------------------------------------------
142  */
143 void
144 DropProceduralLanguage(DropPLangStmt *stmt)
145 {
146         char            languageName[NAMEDATALEN];
147         HeapTuple       langTup;
148         Relation        rel;
149
150         /*
151          * Check permission
152          */
153         if (!superuser())
154                 elog(ERROR, "Only users with Postgres superuser privilege are "
155                          "permitted to drop procedural languages");
156
157         /*
158          * Translate the language name, check that this language exist and is
159          * a PL
160          */
161         case_translate_language_name(stmt->plname, languageName);
162
163         rel = heap_openr(LanguageRelationName, RowExclusiveLock);
164
165         langTup = SearchSysCacheCopy(LANGNAME,
166                                                                  PointerGetDatum(languageName),
167                                                                  0, 0, 0);
168         if (!HeapTupleIsValid(langTup))
169                 elog(ERROR, "Language %s doesn't exist", languageName);
170
171         if (!((Form_pg_language) GETSTRUCT(langTup))->lanispl)
172                 elog(ERROR, "Language %s isn't a created procedural language",
173                          languageName);
174
175         simple_heap_delete(rel, &langTup->t_self);
176
177         heap_freetuple(langTup);
178         heap_close(rel, RowExclusiveLock);
179 }