1 /*-------------------------------------------------------------------------
4 * PostgreSQL PROCEDURAL LANGUAGE support code.
6 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.28 2001/06/13 21:44:40 tgl Exp $
12 *-------------------------------------------------------------------------
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"
25 #include "miscadmin.h"
26 #include "utils/builtins.h"
27 #include "utils/syscache.h"
31 case_translate_language_name(const char *input, char *output)
33 /*-------------------------------------------------------------------------
34 Translate the input language name to lower case, except if it's C,
35 translate to upper case.
36 --------------------------------------------------------------------------*/
39 for (i = 0; i < NAMEDATALEN && input[i]; ++i)
40 output[i] = tolower((unsigned char) input[i]);
44 if (strcmp(output, "c") == 0)
49 /* ---------------------------------------------------------------------
50 * CREATE PROCEDURAL LANGUAGE
51 * ---------------------------------------------------------------------
54 CreateProceduralLanguage(CreatePLangStmt *stmt)
56 char languageName[NAMEDATALEN];
59 Oid typev[FUNC_MAX_ARGS];
60 char nulls[Natts_pg_language];
61 Datum values[Natts_pg_language];
72 elog(ERROR, "Only users with Postgres superuser privilege are "
73 "permitted to create procedural languages");
76 * Translate the language name and check that this language doesn't
79 case_translate_language_name(stmt->plname, languageName);
81 if (SearchSysCacheExists(LANGNAME,
82 PointerGetDatum(languageName),
84 elog(ERROR, "Language %s already exists", languageName);
87 * Lookup the PL handler function and check that it is of return type
90 memset(typev, 0, sizeof(typev));
91 procTup = SearchSysCache(PROCNAME,
92 PointerGetDatum(stmt->plhandler),
94 PointerGetDatum(typev),
96 if (!HeapTupleIsValid(procTup))
97 elog(ERROR, "PL handler function %s() doesn't exist",
99 if (((Form_pg_proc) GETSTRUCT(procTup))->prorettype != InvalidOid)
100 elog(ERROR, "PL handler function %s() isn't of return type Opaque",
104 * Insert the new language into pg_language
106 for (i = 0; i < Natts_pg_language; i++)
109 values[i] = (Datum) NULL;
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));
120 ReleaseSysCache(procTup);
122 rel = heap_openr(LanguageRelationName, RowExclusiveLock);
124 tupDesc = rel->rd_att;
125 tup = heap_formtuple(tupDesc, values, nulls);
127 heap_insert(rel, tup);
129 if (RelationGetForm(rel)->relhasindex)
131 Relation idescs[Num_pg_language_indices];
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);
138 heap_close(rel, RowExclusiveLock);
142 /* ---------------------------------------------------------------------
143 * DROP PROCEDURAL LANGUAGE
144 * ---------------------------------------------------------------------
147 DropProceduralLanguage(DropPLangStmt *stmt)
149 char languageName[NAMEDATALEN];
157 elog(ERROR, "Only users with Postgres superuser privilege are "
158 "permitted to drop procedural languages");
161 * Translate the language name, check that this language exist and is
164 case_translate_language_name(stmt->plname, languageName);
166 rel = heap_openr(LanguageRelationName, RowExclusiveLock);
168 langTup = SearchSysCacheCopy(LANGNAME,
169 PointerGetDatum(languageName),
171 if (!HeapTupleIsValid(langTup))
172 elog(ERROR, "Language %s doesn't exist", languageName);
174 if (!((Form_pg_language) GETSTRUCT(langTup))->lanispl)
175 elog(ERROR, "Language %s isn't a created procedural language",
178 simple_heap_delete(rel, &langTup->t_self);
180 heap_freetuple(langTup);
181 heap_close(rel, RowExclusiveLock);