Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7bff4c5

Browse files
committed
Now we are able to CREATE PROCEDURAL LANGUAGE (Thanks, Jan).
1 parent 9db2992 commit 7bff4c5

File tree

16 files changed

+638
-145
lines changed

16 files changed

+638
-145
lines changed

src/backend/commands/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Makefile for commands
55
#
66
# IDENTIFICATION
7-
# $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.4 1997/08/31 11:40:12 vadim Exp $
7+
# $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.5 1997/10/28 14:54:43 vadim Exp $
88
#
99
#-------------------------------------------------------------------------
1010

@@ -19,7 +19,7 @@ CFLAGS+=$(INCLUDE_OPT)
1919

2020
OBJS = async.o creatinh.o command.o copy.o defind.o define.o \
2121
purge.o remove.o rename.o vacuum.o version.o view.o cluster.o \
22-
recipe.o explain.o sequence.o trigger.o
22+
recipe.o explain.o sequence.o trigger.o proclang.o
2323

2424
all: SUBSYS.o
2525

src/backend/commands/define.c

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.16 1997/09/08 21:42:38 momjian Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.17 1997/10/28 14:54:46 vadim Exp $
1313
*
1414
* DESCRIPTION
1515
* The "DefineFoo" routines take the parse tree and pick out the
@@ -45,6 +45,7 @@
4545
#include <catalog/pg_operator.h>
4646
#include <catalog/pg_proc.h>
4747
#include <catalog/pg_type.h>
48+
#include <catalog/pg_language.h>
4849
#include <utils/syscache.h>
4950
#include <fmgr.h> /* for fmgr */
5051
#include <utils/builtins.h> /* prototype for textin() */
@@ -239,6 +240,8 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
239240
bool canCache;
240241
bool returnsSet;
241242

243+
bool lanisPL = false;
244+
242245
/* The function returns a set of values, as opposed to a singleton. */
243246

244247

@@ -262,19 +265,59 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
262265
}
263266
else
264267
{
265-
elog(WARN,
268+
HeapTuple languageTuple;
269+
Form_pg_language languageStruct;
270+
271+
/* Lookup the language in the system cache */
272+
languageTuple = SearchSysCacheTuple(LANNAME,
273+
PointerGetDatum(languageName),
274+
0, 0, 0);
275+
276+
if (!HeapTupleIsValid(languageTuple)) {
277+
278+
elog(WARN,
266279
"Unrecognized language specified in a CREATE FUNCTION: "
267-
"'%s'. Recognized languages are sql, C, and internal.",
280+
"'%s'. Recognized languages are sql, C, internal "
281+
"and the created procedural languages.",
268282
languageName);
283+
}
284+
285+
/* Check that this language is a PL */
286+
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
287+
if (!(languageStruct->lanispl)) {
288+
elog(WARN,
289+
"Language '%s' isn't defined as PL", languageName);
290+
}
291+
292+
/*
293+
* Functions in untrusted procedural languages are
294+
* restricted to be defined by postgres superusers only
295+
*/
296+
if (languageStruct->lanpltrusted == false && !superuser()) {
297+
elog(WARN, "Only users with Postgres superuser privilege "
298+
"are permitted to create a function in the '%s' "
299+
"language.",
300+
languageName);
301+
}
302+
303+
lanisPL = true;
304+
305+
/*
306+
* These are meaningless
307+
*/
308+
perbyte_cpu = percall_cpu = 0;
309+
byte_pct = outin_ratio = 100;
310+
canCache = false;
269311
}
270312

271313
interpret_AS_clause(languageName, stmt->as, &prosrc_str, &probin_str);
272314

273-
if (strcmp(languageName, "sql") != 0 && !superuser())
315+
if (strcmp(languageName, "sql") != 0 && lanisPL == false && !superuser())
274316
elog(WARN,
275317
"Only users with Postgres superuser privilege are permitted "
276318
"to create a function "
277-
"in the '%s' language. Others may use the 'sql' language.",
319+
"in the '%s' language. Others may use the 'sql' language "
320+
"or the created procedural languages.",
278321
languageName);
279322
/* Above does not return. */
280323
else

src/backend/commands/proclang.c

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

0 commit comments

Comments
 (0)