OSDN Git Service

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