1
/*-------------------------------------------------------------------------
4
* PostgreSQL PROCEDURAL LANGUAGE support code.
6
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
7
* Portions Copyright (c) 1994, Regents of the University of California
10
* src/backend/commands/proclang.c
12
*-------------------------------------------------------------------------
16
#include "access/genam.h"
17
#include "access/heapam.h"
18
#include "catalog/dependency.h"
19
#include "catalog/indexing.h"
20
#include "catalog/objectaccess.h"
21
#include "catalog/pg_language.h"
22
#include "catalog/pg_namespace.h"
23
#include "catalog/pg_pltemplate.h"
24
#include "catalog/pg_proc.h"
25
#include "catalog/pg_proc_fn.h"
26
#include "catalog/pg_type.h"
27
#include "commands/dbcommands.h"
28
#include "commands/defrem.h"
29
#include "commands/proclang.h"
30
#include "miscadmin.h"
31
#include "parser/parse_func.h"
32
#include "parser/parser.h"
33
#include "utils/acl.h"
34
#include "utils/builtins.h"
35
#include "utils/fmgroids.h"
36
#include "utils/lsyscache.h"
37
#include "utils/rel.h"
38
#include "utils/syscache.h"
39
#include "utils/tqual.h"
44
bool tmpltrusted; /* trusted? */
45
bool tmpldbacreate; /* db owner allowed to create? */
46
char *tmplhandler; /* name of handler function */
47
char *tmplinline; /* name of anonymous-block handler, or NULL */
48
char *tmplvalidator; /* name of validator function, or NULL */
49
char *tmpllibrary; /* path of shared library */
52
static void create_proc_lang(const char *languageName, bool replace,
53
Oid languageOwner, Oid handlerOid, Oid inlineOid,
54
Oid valOid, bool trusted);
55
static PLTemplate *find_language_template(const char *languageName);
56
static void AlterLanguageOwner_internal(HeapTuple tup, Relation rel,
60
/* ---------------------------------------------------------------------
61
* CREATE PROCEDURAL LANGUAGE
62
* ---------------------------------------------------------------------
65
CreateProceduralLanguage(CreatePLangStmt *stmt)
68
PLTemplate *pltemplate;
76
* Translate the language name to lower case
78
languageName = case_translate_language_name(stmt->plname);
81
* If we have template information for the language, ignore the supplied
82
* parameters (if any) and use the template information.
84
if ((pltemplate = find_language_template(languageName)) != NULL)
89
* Give a notice if we are ignoring supplied parameters.
93
(errmsg("using pg_pltemplate information instead of CREATE LANGUAGE parameters")));
100
if (!pltemplate->tmpldbacreate)
102
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
103
errmsg("must be superuser to create procedural language \"%s\"",
105
if (!pg_database_ownercheck(MyDatabaseId, GetUserId()))
106
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
107
get_database_name(MyDatabaseId));
111
* Find or create the handler function, which we force to be in the
112
* pg_catalog schema. If already present, it must have the correct
115
funcname = SystemFuncName(pltemplate->tmplhandler);
116
handlerOid = LookupFuncName(funcname, 0, funcargtypes, true);
117
if (OidIsValid(handlerOid))
119
funcrettype = get_func_rettype(handlerOid);
120
if (funcrettype != LANGUAGE_HANDLEROID)
122
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
123
errmsg("function %s must return type \"language_handler\"",
124
NameListToString(funcname))));
128
handlerOid = ProcedureCreate(pltemplate->tmplhandler,
129
PG_CATALOG_NAMESPACE,
131
false, /* returnsSet */
135
pltemplate->tmplhandler,
136
pltemplate->tmpllibrary,
138
false, /* isWindowFunc */
139
false, /* security_definer */
140
false, /* isStrict */
141
PROVOLATILE_VOLATILE,
142
buildoidvector(funcargtypes, 0),
143
PointerGetDatum(NULL),
144
PointerGetDatum(NULL),
145
PointerGetDatum(NULL),
147
PointerGetDatum(NULL),
153
* Likewise for the anonymous block handler, if required; but we don't
154
* care about its return type.
156
if (pltemplate->tmplinline)
158
funcname = SystemFuncName(pltemplate->tmplinline);
159
funcargtypes[0] = INTERNALOID;
160
inlineOid = LookupFuncName(funcname, 1, funcargtypes, true);
161
if (!OidIsValid(inlineOid))
163
inlineOid = ProcedureCreate(pltemplate->tmplinline,
164
PG_CATALOG_NAMESPACE,
166
false, /* returnsSet */
170
pltemplate->tmplinline,
171
pltemplate->tmpllibrary,
173
false, /* isWindowFunc */
174
false, /* security_definer */
176
PROVOLATILE_VOLATILE,
177
buildoidvector(funcargtypes, 1),
178
PointerGetDatum(NULL),
179
PointerGetDatum(NULL),
180
PointerGetDatum(NULL),
182
PointerGetDatum(NULL),
188
inlineOid = InvalidOid;
191
* Likewise for the validator, if required; but we don't care about
194
if (pltemplate->tmplvalidator)
196
funcname = SystemFuncName(pltemplate->tmplvalidator);
197
funcargtypes[0] = OIDOID;
198
valOid = LookupFuncName(funcname, 1, funcargtypes, true);
199
if (!OidIsValid(valOid))
201
valOid = ProcedureCreate(pltemplate->tmplvalidator,
202
PG_CATALOG_NAMESPACE,
204
false, /* returnsSet */
208
pltemplate->tmplvalidator,
209
pltemplate->tmpllibrary,
211
false, /* isWindowFunc */
212
false, /* security_definer */
214
PROVOLATILE_VOLATILE,
215
buildoidvector(funcargtypes, 1),
216
PointerGetDatum(NULL),
217
PointerGetDatum(NULL),
218
PointerGetDatum(NULL),
220
PointerGetDatum(NULL),
229
create_proc_lang(languageName, stmt->replace, GetUserId(),
230
handlerOid, inlineOid,
231
valOid, pltemplate->tmpltrusted);
236
* No template, so use the provided information. If there's no
237
* handler clause, the user is trying to rely on a template that we
238
* don't have, so complain accordingly.
240
if (!stmt->plhandler)
242
(errcode(ERRCODE_UNDEFINED_OBJECT),
243
errmsg("unsupported language \"%s\"",
245
errhint("The supported languages are listed in the pg_pltemplate system catalog.")));
252
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
253
errmsg("must be superuser to create custom procedural language")));
256
* Lookup the PL handler function and check that it is of the expected
259
handlerOid = LookupFuncName(stmt->plhandler, 0, funcargtypes, false);
260
funcrettype = get_func_rettype(handlerOid);
261
if (funcrettype != LANGUAGE_HANDLEROID)
264
* We allow OPAQUE just so we can load old dump files. When we
265
* see a handler function declared OPAQUE, change it to
266
* LANGUAGE_HANDLER. (This is probably obsolete and removable?)
268
if (funcrettype == OPAQUEOID)
271
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
272
errmsg("changing return type of function %s from \"opaque\" to \"language_handler\"",
273
NameListToString(stmt->plhandler))));
274
SetFunctionReturnType(handlerOid, LANGUAGE_HANDLEROID);
278
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
279
errmsg("function %s must return type \"language_handler\"",
280
NameListToString(stmt->plhandler))));
283
/* validate the inline function */
286
funcargtypes[0] = INTERNALOID;
287
inlineOid = LookupFuncName(stmt->plinline, 1, funcargtypes, false);
288
/* return value is ignored, so we don't check the type */
291
inlineOid = InvalidOid;
293
/* validate the validator function */
294
if (stmt->plvalidator)
296
funcargtypes[0] = OIDOID;
297
valOid = LookupFuncName(stmt->plvalidator, 1, funcargtypes, false);
298
/* return value is ignored, so we don't check the type */
304
create_proc_lang(languageName, stmt->replace, GetUserId(),
305
handlerOid, inlineOid,
306
valOid, stmt->pltrusted);
311
* Guts of language creation.
314
create_proc_lang(const char *languageName, bool replace,
315
Oid languageOwner, Oid handlerOid, Oid inlineOid,
316
Oid valOid, bool trusted)
320
Datum values[Natts_pg_language];
321
bool nulls[Natts_pg_language];
322
bool replaces[Natts_pg_language];
327
ObjectAddress myself,
330
rel = heap_open(LanguageRelationId, RowExclusiveLock);
331
tupDesc = RelationGetDescr(rel);
333
/* Prepare data to be inserted */
334
memset(values, 0, sizeof(values));
335
memset(nulls, false, sizeof(nulls));
336
memset(replaces, true, sizeof(replaces));
338
namestrcpy(&langname, languageName);
339
values[Anum_pg_language_lanname - 1] = NameGetDatum(&langname);
340
values[Anum_pg_language_lanowner - 1] = ObjectIdGetDatum(languageOwner);
341
values[Anum_pg_language_lanispl - 1] = BoolGetDatum(true);
342
values[Anum_pg_language_lanpltrusted - 1] = BoolGetDatum(trusted);
343
values[Anum_pg_language_lanplcallfoid - 1] = ObjectIdGetDatum(handlerOid);
344
values[Anum_pg_language_laninline - 1] = ObjectIdGetDatum(inlineOid);
345
values[Anum_pg_language_lanvalidator - 1] = ObjectIdGetDatum(valOid);
346
nulls[Anum_pg_language_lanacl - 1] = true;
348
/* Check for pre-existing definition */
349
oldtup = SearchSysCache1(LANGNAME, PointerGetDatum(languageName));
351
if (HeapTupleIsValid(oldtup))
353
/* There is one; okay to replace it? */
356
(errcode(ERRCODE_DUPLICATE_OBJECT),
357
errmsg("language \"%s\" already exists", languageName)));
358
if (!pg_language_ownercheck(HeapTupleGetOid(oldtup), languageOwner))
359
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
363
* Do not change existing ownership or permissions. Note
364
* dependency-update code below has to agree with this decision.
366
replaces[Anum_pg_language_lanowner - 1] = false;
367
replaces[Anum_pg_language_lanacl - 1] = false;
370
tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
371
simple_heap_update(rel, &tup->t_self, tup);
373
ReleaseSysCache(oldtup);
378
/* Creating a new language */
379
tup = heap_form_tuple(tupDesc, values, nulls);
380
simple_heap_insert(rel, tup);
384
/* Need to update indexes for either the insert or update case */
385
CatalogUpdateIndexes(rel, tup);
388
* Create dependencies for the new language. If we are updating an
389
* existing language, first delete any existing pg_depend entries.
390
* (However, since we are not changing ownership or permissions, the
391
* shared dependencies do *not* need to change, and we leave them alone.
392
* We also don't change any pre-existing extension-membership dependency.)
394
myself.classId = LanguageRelationId;
395
myself.objectId = HeapTupleGetOid(tup);
396
myself.objectSubId = 0;
399
deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
401
/* dependency on owner of language */
403
recordDependencyOnOwner(myself.classId, myself.objectId,
406
/* dependency on extension */
408
recordDependencyOnCurrentExtension(&myself);
410
/* dependency on the PL handler function */
411
referenced.classId = ProcedureRelationId;
412
referenced.objectId = handlerOid;
413
referenced.objectSubId = 0;
414
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
416
/* dependency on the inline handler function, if any */
417
if (OidIsValid(inlineOid))
419
referenced.classId = ProcedureRelationId;
420
referenced.objectId = inlineOid;
421
referenced.objectSubId = 0;
422
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
425
/* dependency on the validator function, if any */
426
if (OidIsValid(valOid))
428
referenced.classId = ProcedureRelationId;
429
referenced.objectId = valOid;
430
referenced.objectSubId = 0;
431
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
434
/* Post creation hook for new procedural language */
435
InvokeObjectAccessHook(OAT_POST_CREATE,
436
LanguageRelationId, myself.objectId, 0);
438
heap_close(rel, RowExclusiveLock);
442
* Look to see if we have template information for the given language name.
445
find_language_template(const char *languageName)
453
rel = heap_open(PLTemplateRelationId, AccessShareLock);
456
Anum_pg_pltemplate_tmplname,
457
BTEqualStrategyNumber, F_NAMEEQ,
458
NameGetDatum(languageName));
459
scan = systable_beginscan(rel, PLTemplateNameIndexId, true,
460
SnapshotNow, 1, &key);
462
tup = systable_getnext(scan);
463
if (HeapTupleIsValid(tup))
465
Form_pg_pltemplate tmpl = (Form_pg_pltemplate) GETSTRUCT(tup);
469
result = (PLTemplate *) palloc0(sizeof(PLTemplate));
470
result->tmpltrusted = tmpl->tmpltrusted;
471
result->tmpldbacreate = tmpl->tmpldbacreate;
473
/* Remaining fields are variable-width so we need heap_getattr */
474
datum = heap_getattr(tup, Anum_pg_pltemplate_tmplhandler,
475
RelationGetDescr(rel), &isnull);
477
result->tmplhandler = TextDatumGetCString(datum);
479
datum = heap_getattr(tup, Anum_pg_pltemplate_tmplinline,
480
RelationGetDescr(rel), &isnull);
482
result->tmplinline = TextDatumGetCString(datum);
484
datum = heap_getattr(tup, Anum_pg_pltemplate_tmplvalidator,
485
RelationGetDescr(rel), &isnull);
487
result->tmplvalidator = TextDatumGetCString(datum);
489
datum = heap_getattr(tup, Anum_pg_pltemplate_tmpllibrary,
490
RelationGetDescr(rel), &isnull);
492
result->tmpllibrary = TextDatumGetCString(datum);
494
/* Ignore template if handler or library info is missing */
495
if (!result->tmplhandler || !result->tmpllibrary)
501
systable_endscan(scan);
503
heap_close(rel, AccessShareLock);
510
* This just returns TRUE if we have a valid template for a given language
513
PLTemplateExists(const char *languageName)
515
return (find_language_template(languageName) != NULL);
519
/* ---------------------------------------------------------------------
520
* DROP PROCEDURAL LANGUAGE
521
* ---------------------------------------------------------------------
524
DropProceduralLanguage(DropPLangStmt *stmt)
528
ObjectAddress object;
531
* Translate the language name, check that the language exists
533
languageName = case_translate_language_name(stmt->plname);
535
oid = get_language_oid(languageName, stmt->missing_ok);
536
if (!OidIsValid(oid))
539
(errmsg("language \"%s\" does not exist, skipping",
547
if (!pg_language_ownercheck(oid, GetUserId()))
548
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
551
object.classId = LanguageRelationId;
552
object.objectId = oid;
553
object.objectSubId = 0;
558
performDeletion(&object, stmt->behavior);
562
* Guts of language dropping.
565
DropProceduralLanguageById(Oid langOid)
570
rel = heap_open(LanguageRelationId, RowExclusiveLock);
572
langTup = SearchSysCache1(LANGOID, ObjectIdGetDatum(langOid));
573
if (!HeapTupleIsValid(langTup)) /* should not happen */
574
elog(ERROR, "cache lookup failed for language %u", langOid);
576
simple_heap_delete(rel, &langTup->t_self);
578
ReleaseSysCache(langTup);
580
heap_close(rel, RowExclusiveLock);
587
RenameLanguage(const char *oldname, const char *newname)
592
/* Translate both names for consistency with CREATE */
593
oldname = case_translate_language_name(oldname);
594
newname = case_translate_language_name(newname);
596
rel = heap_open(LanguageRelationId, RowExclusiveLock);
598
tup = SearchSysCacheCopy1(LANGNAME, CStringGetDatum(oldname));
599
if (!HeapTupleIsValid(tup))
601
(errcode(ERRCODE_UNDEFINED_OBJECT),
602
errmsg("language \"%s\" does not exist", oldname)));
604
/* make sure the new name doesn't exist */
605
if (SearchSysCacheExists1(LANGNAME, CStringGetDatum(newname)))
607
(errcode(ERRCODE_DUPLICATE_OBJECT),
608
errmsg("language \"%s\" already exists", newname)));
610
/* must be owner of PL */
611
if (!pg_language_ownercheck(HeapTupleGetOid(tup), GetUserId()))
612
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
616
namestrcpy(&(((Form_pg_language) GETSTRUCT(tup))->lanname), newname);
617
simple_heap_update(rel, &tup->t_self, tup);
618
CatalogUpdateIndexes(rel, tup);
620
heap_close(rel, NoLock);
625
* Change language owner
628
AlterLanguageOwner(const char *name, Oid newOwnerId)
633
/* Translate name for consistency with CREATE */
634
name = case_translate_language_name(name);
636
rel = heap_open(LanguageRelationId, RowExclusiveLock);
638
tup = SearchSysCache1(LANGNAME, CStringGetDatum(name));
639
if (!HeapTupleIsValid(tup))
641
(errcode(ERRCODE_UNDEFINED_OBJECT),
642
errmsg("language \"%s\" does not exist", name)));
644
AlterLanguageOwner_internal(tup, rel, newOwnerId);
646
ReleaseSysCache(tup);
648
heap_close(rel, RowExclusiveLock);
653
* Change language owner, specified by OID
656
AlterLanguageOwner_oid(Oid oid, Oid newOwnerId)
661
rel = heap_open(LanguageRelationId, RowExclusiveLock);
663
tup = SearchSysCache1(LANGOID, ObjectIdGetDatum(oid));
664
if (!HeapTupleIsValid(tup))
665
elog(ERROR, "cache lookup failed for language %u", oid);
667
AlterLanguageOwner_internal(tup, rel, newOwnerId);
669
ReleaseSysCache(tup);
671
heap_close(rel, RowExclusiveLock);
675
* Workhorse for AlterLanguageOwner variants
678
AlterLanguageOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId)
680
Form_pg_language lanForm;
682
lanForm = (Form_pg_language) GETSTRUCT(tup);
685
* If the new owner is the same as the existing owner, consider the
686
* command to have succeeded. This is for dump restoration purposes.
688
if (lanForm->lanowner != newOwnerId)
690
Datum repl_val[Natts_pg_language];
691
bool repl_null[Natts_pg_language];
692
bool repl_repl[Natts_pg_language];
698
/* Otherwise, must be owner of the existing object */
699
if (!pg_language_ownercheck(HeapTupleGetOid(tup), GetUserId()))
700
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
701
NameStr(lanForm->lanname));
703
/* Must be able to become new owner */
704
check_is_member_of_role(GetUserId(), newOwnerId);
706
memset(repl_null, false, sizeof(repl_null));
707
memset(repl_repl, false, sizeof(repl_repl));
709
repl_repl[Anum_pg_language_lanowner - 1] = true;
710
repl_val[Anum_pg_language_lanowner - 1] = ObjectIdGetDatum(newOwnerId);
713
* Determine the modified ACL for the new owner. This is only
714
* necessary when the ACL is non-null.
716
aclDatum = SysCacheGetAttr(LANGNAME, tup,
717
Anum_pg_language_lanacl,
721
newAcl = aclnewowner(DatumGetAclP(aclDatum),
722
lanForm->lanowner, newOwnerId);
723
repl_repl[Anum_pg_language_lanacl - 1] = true;
724
repl_val[Anum_pg_language_lanacl - 1] = PointerGetDatum(newAcl);
727
newtuple = heap_modify_tuple(tup, RelationGetDescr(rel),
728
repl_val, repl_null, repl_repl);
730
simple_heap_update(rel, &newtuple->t_self, newtuple);
731
CatalogUpdateIndexes(rel, newtuple);
733
heap_freetuple(newtuple);
735
/* Update owner dependency reference */
736
changeDependencyOnOwner(LanguageRelationId, HeapTupleGetOid(tup),
742
* get_language_oid - given a language name, look up the OID
744
* If missing_ok is false, throw an error if language name not found. If
745
* true, just return InvalidOid.
748
get_language_oid(const char *langname, bool missing_ok)
752
oid = GetSysCacheOid1(LANGNAME, CStringGetDatum(langname));
753
if (!OidIsValid(oid) && !missing_ok)
755
(errcode(ERRCODE_UNDEFINED_OBJECT),
756
errmsg("language \"%s\" does not exist", langname)));