]> granicus.if.org Git - postgresql/blob - src/backend/commands/proclang.c
120c5d8b008c8f0865c74c0fd4b0c6b2871f3258
[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.28 2001/06/13 21:44:40 tgl 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 static void
31 case_translate_language_name(const char *input, char *output)
32 {
33 /*-------------------------------------------------------------------------
34   Translate the input language name to lower case, except if it's C,
35   translate to upper case.
36 --------------------------------------------------------------------------*/
37         int                     i;
38
39         for (i = 0; i < NAMEDATALEN && input[i]; ++i)
40                 output[i] = tolower((unsigned char) input[i]);
41
42         output[i] = '\0';
43
44         if (strcmp(output, "c") == 0)
45                 output[0] = 'C';
46 }
47
48
49 /* ---------------------------------------------------------------------
50  * CREATE PROCEDURAL LANGUAGE
51  * ---------------------------------------------------------------------
52  */
53 void
54 CreateProceduralLanguage(CreatePLangStmt *stmt)
55 {
56         char            languageName[NAMEDATALEN];
57         HeapTuple       procTup;
58
59         Oid                     typev[FUNC_MAX_ARGS];
60         char            nulls[Natts_pg_language];
61         Datum           values[Natts_pg_language];
62         Relation        rel;
63         HeapTuple       tup;
64         TupleDesc       tupDesc;
65
66         int                     i;
67
68         /*
69          * Check permission
70          */
71         if (!superuser())
72                 elog(ERROR, "Only users with Postgres superuser privilege are "
73                          "permitted to create procedural languages");
74
75         /*
76          * Translate the language name and check that this language doesn't
77          * already exist
78          */
79         case_translate_language_name(stmt->plname, languageName);
80
81         if (SearchSysCacheExists(LANGNAME,
82                                                          PointerGetDatum(languageName),
83                                                          0, 0, 0))
84                 elog(ERROR, "Language %s already exists", languageName);
85
86         /*
87          * Lookup the PL handler function and check that it is of return type
88          * Opaque
89          */
90         memset(typev, 0, sizeof(typev));
91         procTup = SearchSysCache(PROCNAME,
92                                                          PointerGetDatum(stmt->plhandler),
93                                                          Int32GetDatum(0),
94                                                          PointerGetDatum(typev),
95                                                          0);
96         if (!HeapTupleIsValid(procTup))
97                 elog(ERROR, "PL handler function %s() doesn't exist",
98                          stmt->plhandler);
99         if (((Form_pg_proc) GETSTRUCT(procTup))->prorettype != InvalidOid)
100                 elog(ERROR, "PL handler function %s() isn't of return type Opaque",
101                          stmt->plhandler);
102
103         /*
104          * Insert the new language into pg_language
105          */
106         for (i = 0; i < Natts_pg_language; i++)
107         {
108                 nulls[i] = ' ';
109                 values[i] = (Datum) NULL;
110         }
111
112         i = 0;
113         values[i++] = PointerGetDatum(languageName);
114         values[i++] = BoolGetDatum(true);       /* lanispl */
115         values[i++] = BoolGetDatum(stmt->pltrusted);
116         values[i++] = ObjectIdGetDatum(procTup->t_data->t_oid);
117         values[i++] = DirectFunctionCall1(textin,
118                                                                           CStringGetDatum(stmt->plcompiler));
119
120         ReleaseSysCache(procTup);
121
122         rel = heap_openr(LanguageRelationName, RowExclusiveLock);
123
124         tupDesc = rel->rd_att;
125         tup = heap_formtuple(tupDesc, values, nulls);
126
127         heap_insert(rel, tup);
128
129         if (RelationGetForm(rel)->relhasindex)
130         {
131                 Relation        idescs[Num_pg_language_indices];
132
133                 CatalogOpenIndices(Num_pg_language_indices, Name_pg_language_indices, idescs);
134                 CatalogIndexInsert(idescs, Num_pg_language_indices, rel, tup);
135                 CatalogCloseIndices(Num_pg_language_indices, idescs);
136         }
137
138         heap_close(rel, RowExclusiveLock);
139 }
140
141
142 /* ---------------------------------------------------------------------
143  * DROP PROCEDURAL LANGUAGE
144  * ---------------------------------------------------------------------
145  */
146 void
147 DropProceduralLanguage(DropPLangStmt *stmt)
148 {
149         char            languageName[NAMEDATALEN];
150         HeapTuple       langTup;
151         Relation        rel;
152
153         /*
154          * Check permission
155          */
156         if (!superuser())
157                 elog(ERROR, "Only users with Postgres superuser privilege are "
158                          "permitted to drop procedural languages");
159
160         /*
161          * Translate the language name, check that this language exist and is
162          * a PL
163          */
164         case_translate_language_name(stmt->plname, languageName);
165
166         rel = heap_openr(LanguageRelationName, RowExclusiveLock);
167
168         langTup = SearchSysCacheCopy(LANGNAME,
169                                                                  PointerGetDatum(languageName),
170                                                                  0, 0, 0);
171         if (!HeapTupleIsValid(langTup))
172                 elog(ERROR, "Language %s doesn't exist", languageName);
173
174         if (!((Form_pg_language) GETSTRUCT(langTup))->lanispl)
175                 elog(ERROR, "Language %s isn't a created procedural language",
176                          languageName);
177
178         simple_heap_delete(rel, &langTup->t_self);
179
180         heap_freetuple(langTup);
181         heap_close(rel, RowExclusiveLock);
182 }