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.29 2002/02/18 23:11:11 petere 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 * Translate the input language name to lower case.
34 case_translate_language_name(const char *input, char *output)
38 for (i = 0; i < NAMEDATALEN && input[i]; ++i)
39 output[i] = tolower((unsigned char) input[i]);
45 /* ---------------------------------------------------------------------
46 * CREATE PROCEDURAL LANGUAGE
47 * ---------------------------------------------------------------------
50 CreateProceduralLanguage(CreatePLangStmt *stmt)
52 char languageName[NAMEDATALEN];
55 Oid typev[FUNC_MAX_ARGS];
56 char nulls[Natts_pg_language];
57 Datum values[Natts_pg_language];
68 elog(ERROR, "Only users with Postgres superuser privilege are "
69 "permitted to create procedural languages");
72 * Translate the language name and check that this language doesn't
75 case_translate_language_name(stmt->plname, languageName);
77 if (SearchSysCacheExists(LANGNAME,
78 PointerGetDatum(languageName),
80 elog(ERROR, "Language %s already exists", languageName);
83 * Lookup the PL handler function and check that it is of return type
86 memset(typev, 0, sizeof(typev));
87 procTup = SearchSysCache(PROCNAME,
88 PointerGetDatum(stmt->plhandler),
90 PointerGetDatum(typev),
92 if (!HeapTupleIsValid(procTup))
93 elog(ERROR, "PL handler function %s() doesn't exist",
95 if (((Form_pg_proc) GETSTRUCT(procTup))->prorettype != InvalidOid)
96 elog(ERROR, "PL handler function %s() isn't of return type Opaque",
100 * Insert the new language into pg_language
102 for (i = 0; i < Natts_pg_language; i++)
105 values[i] = (Datum) NULL;
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 */
117 ReleaseSysCache(procTup);
119 rel = heap_openr(LanguageRelationName, RowExclusiveLock);
121 tupDesc = rel->rd_att;
122 tup = heap_formtuple(tupDesc, values, nulls);
124 heap_insert(rel, tup);
126 if (RelationGetForm(rel)->relhasindex)
128 Relation idescs[Num_pg_language_indices];
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);
135 heap_close(rel, RowExclusiveLock);
139 /* ---------------------------------------------------------------------
140 * DROP PROCEDURAL LANGUAGE
141 * ---------------------------------------------------------------------
144 DropProceduralLanguage(DropPLangStmt *stmt)
146 char languageName[NAMEDATALEN];
154 elog(ERROR, "Only users with Postgres superuser privilege are "
155 "permitted to drop procedural languages");
158 * Translate the language name, check that this language exist and is
161 case_translate_language_name(stmt->plname, languageName);
163 rel = heap_openr(LanguageRelationName, RowExclusiveLock);
165 langTup = SearchSysCacheCopy(LANGNAME,
166 PointerGetDatum(languageName),
168 if (!HeapTupleIsValid(langTup))
169 elog(ERROR, "Language %s doesn't exist", languageName);
171 if (!((Form_pg_language) GETSTRUCT(langTup))->lanispl)
172 elog(ERROR, "Language %s isn't a created procedural language",
175 simple_heap_delete(rel, &langTup->t_self);
177 heap_freetuple(langTup);
178 heap_close(rel, RowExclusiveLock);