1 /*-------------------------------------------------------------------------
4 * PostgreSQL PROCEDURAL LANGUAGE support code.
6 *-------------------------------------------------------------------------
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"
20 #include "utils/syscache.h"
24 case_translate_language_name(const char *input, char *output)
26 /*-------------------------------------------------------------------------
27 Translate the input language name to lower case, except if it's C,
28 translate to upper case.
29 --------------------------------------------------------------------------*/
32 for (i = 0; i < NAMEDATALEN && input[i]; ++i)
33 output[i] = tolower(input[i]);
37 if (strcmp(output, "c") == 0)
42 /* ---------------------------------------------------------------------
43 * CREATE PROCEDURAL LANGUAGE
44 * ---------------------------------------------------------------------
47 CreateProceduralLanguage(CreatePLangStmt *stmt)
49 char languageName[NAMEDATALEN];
54 char nulls[Natts_pg_language];
55 Datum values[Natts_pg_language];
68 elog(ERROR, "Only users with Postgres superuser privilege are "
69 "permitted to create procedural languages");
73 * Translate the language name and check that
74 * this language doesn't already exist
77 case_translate_language_name(stmt->plname, languageName);
79 langTup = SearchSysCacheTuple(LANGNAME,
80 PointerGetDatum(languageName),
82 if (HeapTupleIsValid(langTup))
83 elog(ERROR, "Language %s already exists", languageName);
86 * Lookup the PL handler function and check that it is
87 * of return type Opaque
90 memset(typev, 0, sizeof(typev));
91 procTup = SearchSysCacheTuple(PROCNAME,
92 PointerGetDatum(stmt->plhandler),
94 PointerGetDatum(typev),
96 if (!HeapTupleIsValid(procTup))
98 elog(ERROR, "PL handler function %s() doesn't exist",
101 if (((Form_pg_proc) GETSTRUCT(procTup))->prorettype != InvalidOid)
103 elog(ERROR, "PL handler function %s() isn't of return type Opaque",
108 * Insert the new language into pg_language
111 for (i = 0; i < Natts_pg_language; i++)
114 values[i] = (Datum) NULL;
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);
124 rel = heap_openr(LanguageRelationName, RowExclusiveLock);
126 tupDesc = rel->rd_att;
127 tup = heap_formtuple(tupDesc, values, nulls);
129 heap_insert(rel, tup);
131 if (RelationGetForm(rel)->relhasindex)
133 Relation idescs[Num_pg_language_indices];
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);
140 heap_close(rel, RowExclusiveLock);
144 /* ---------------------------------------------------------------------
145 * DROP PROCEDURAL LANGUAGE
146 * ---------------------------------------------------------------------
149 DropProceduralLanguage(DropPLangStmt *stmt)
151 char languageName[NAMEDATALEN];
161 elog(ERROR, "Only users with Postgres superuser privilege are "
162 "permitted to drop procedural languages");
166 * Translate the language name, check that
167 * this language exist and is a PL
170 case_translate_language_name(stmt->plname, languageName);
172 rel = heap_openr(LanguageRelationName, RowExclusiveLock);
174 langTup = SearchSysCacheTupleCopy(LANGNAME,
175 PointerGetDatum(languageName),
177 if (!HeapTupleIsValid(langTup))
178 elog(ERROR, "Language %s doesn't exist", languageName);
180 if (!((Form_pg_language) GETSTRUCT(langTup))->lanispl)
181 elog(ERROR, "Language %s isn't a created procedural language",
184 heap_delete(rel, &langTup->t_self, NULL);
186 heap_freetuple(langTup);
187 heap_close(rel, RowExclusiveLock);