PostgreSQL Source Code  git master
proclang.c File Reference
#include "postgres.h"
#include "access/table.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_language.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "commands/proclang.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for proclang.c:

Go to the source code of this file.

Functions

ObjectAddress CreateProceduralLanguage (CreatePLangStmt *stmt)
 
Oid get_language_oid (const char *langname, bool missing_ok)
 

Function Documentation

◆ CreateProceduralLanguage()

ObjectAddress CreateProceduralLanguage ( CreatePLangStmt stmt)

Definition at line 39 of file proclang.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, add_exact_object_address(), Assert, BoolGetDatum, CatalogTupleInsert(), CatalogTupleUpdate(), ObjectAddress::classId, deleteDependencyRecordsFor(), DEPENDENCY_NORMAL, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, free_object_addresses(), get_func_rettype(), GetNewOidWithIndex(), GETSTRUCT, GetUserId(), heap_form_tuple(), heap_modify_tuple(), HeapTupleIsValid, InvalidOid, InvokeObjectPostCreateHook, LANGNAME, LanguageOidIndexId, LookupFuncName(), NameGetDatum, NameListToString(), namestrcpy(), new_object_addresses(), OBJECT_LANGUAGE, ObjectAddressSet, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, pg_language_ownercheck(), CreatePLangStmt::plhandler, CreatePLangStmt::plinline, CreatePLangStmt::plname, CreatePLangStmt::pltrusted, CreatePLangStmt::plvalidator, PointerGetDatum, record_object_address_dependencies(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), RelationGetDescr, ReleaseSysCache(), CreatePLangStmt::replace, RowExclusiveLock, SearchSysCache1(), superuser(), HeapTupleData::t_self, table_close(), table_open(), and values.

Referenced by ProcessUtilitySlow().

40 {
41  const char *languageName = stmt->plname;
42  Oid languageOwner = GetUserId();
43  Oid handlerOid,
44  inlineOid,
45  valOid;
46  Oid funcrettype;
47  Oid funcargtypes[1];
48  Relation rel;
49  TupleDesc tupDesc;
50  Datum values[Natts_pg_language];
51  bool nulls[Natts_pg_language];
52  bool replaces[Natts_pg_language];
53  NameData langname;
54  HeapTuple oldtup;
55  HeapTuple tup;
56  Oid langoid;
57  bool is_update;
58  ObjectAddress myself,
59  referenced;
60  ObjectAddresses *addrs;
61 
62  /*
63  * Check permission
64  */
65  if (!superuser())
66  ereport(ERROR,
67  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
68  errmsg("must be superuser to create custom procedural language")));
69 
70  /*
71  * Lookup the PL handler function and check that it is of the expected
72  * return type
73  */
74  Assert(stmt->plhandler);
75  handlerOid = LookupFuncName(stmt->plhandler, 0, NULL, false);
76  funcrettype = get_func_rettype(handlerOid);
77  if (funcrettype != LANGUAGE_HANDLEROID)
78  ereport(ERROR,
79  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
80  errmsg("function %s must return type %s",
81  NameListToString(stmt->plhandler), "language_handler")));
82 
83  /* validate the inline function */
84  if (stmt->plinline)
85  {
86  funcargtypes[0] = INTERNALOID;
87  inlineOid = LookupFuncName(stmt->plinline, 1, funcargtypes, false);
88  /* return value is ignored, so we don't check the type */
89  }
90  else
91  inlineOid = InvalidOid;
92 
93  /* validate the validator function */
94  if (stmt->plvalidator)
95  {
96  funcargtypes[0] = OIDOID;
97  valOid = LookupFuncName(stmt->plvalidator, 1, funcargtypes, false);
98  /* return value is ignored, so we don't check the type */
99  }
100  else
101  valOid = InvalidOid;
102 
103  /* ok to create it */
104  rel = table_open(LanguageRelationId, RowExclusiveLock);
105  tupDesc = RelationGetDescr(rel);
106 
107  /* Prepare data to be inserted */
108  memset(values, 0, sizeof(values));
109  memset(nulls, false, sizeof(nulls));
110  memset(replaces, true, sizeof(replaces));
111 
112  namestrcpy(&langname, languageName);
113  values[Anum_pg_language_lanname - 1] = NameGetDatum(&langname);
114  values[Anum_pg_language_lanowner - 1] = ObjectIdGetDatum(languageOwner);
115  values[Anum_pg_language_lanispl - 1] = BoolGetDatum(true);
116  values[Anum_pg_language_lanpltrusted - 1] = BoolGetDatum(stmt->pltrusted);
117  values[Anum_pg_language_lanplcallfoid - 1] = ObjectIdGetDatum(handlerOid);
118  values[Anum_pg_language_laninline - 1] = ObjectIdGetDatum(inlineOid);
119  values[Anum_pg_language_lanvalidator - 1] = ObjectIdGetDatum(valOid);
120  nulls[Anum_pg_language_lanacl - 1] = true;
121 
122  /* Check for pre-existing definition */
123  oldtup = SearchSysCache1(LANGNAME, PointerGetDatum(languageName));
124 
125  if (HeapTupleIsValid(oldtup))
126  {
127  Form_pg_language oldform = (Form_pg_language) GETSTRUCT(oldtup);
128 
129  /* There is one; okay to replace it? */
130  if (!stmt->replace)
131  ereport(ERROR,
133  errmsg("language \"%s\" already exists", languageName)));
134 
135  /* This is currently pointless, since we already checked superuser */
136 #ifdef NOT_USED
137  if (!pg_language_ownercheck(oldform->oid, languageOwner))
139  languageName);
140 #endif
141 
142  /*
143  * Do not change existing oid, ownership or permissions. Note
144  * dependency-update code below has to agree with this decision.
145  */
146  replaces[Anum_pg_language_oid - 1] = false;
147  replaces[Anum_pg_language_lanowner - 1] = false;
148  replaces[Anum_pg_language_lanacl - 1] = false;
149 
150  /* Okay, do it... */
151  tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
152  CatalogTupleUpdate(rel, &tup->t_self, tup);
153 
154  langoid = oldform->oid;
155  ReleaseSysCache(oldtup);
156  is_update = true;
157  }
158  else
159  {
160  /* Creating a new language */
161  langoid = GetNewOidWithIndex(rel, LanguageOidIndexId,
162  Anum_pg_language_oid);
163  values[Anum_pg_language_oid - 1] = ObjectIdGetDatum(langoid);
164  tup = heap_form_tuple(tupDesc, values, nulls);
165  CatalogTupleInsert(rel, tup);
166  is_update = false;
167  }
168 
169  /*
170  * Create dependencies for the new language. If we are updating an
171  * existing language, first delete any existing pg_depend entries.
172  * (However, since we are not changing ownership or permissions, the
173  * shared dependencies do *not* need to change, and we leave them alone.)
174  */
175  myself.classId = LanguageRelationId;
176  myself.objectId = langoid;
177  myself.objectSubId = 0;
178 
179  if (is_update)
180  deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
181 
182  /* dependency on owner of language */
183  if (!is_update)
185  languageOwner);
186 
187  /* dependency on extension */
188  recordDependencyOnCurrentExtension(&myself, is_update);
189 
190  addrs = new_object_addresses();
191 
192  /* dependency on the PL handler function */
193  ObjectAddressSet(referenced, ProcedureRelationId, handlerOid);
194  add_exact_object_address(&referenced, addrs);
195 
196  /* dependency on the inline handler function, if any */
197  if (OidIsValid(inlineOid))
198  {
199  ObjectAddressSet(referenced, ProcedureRelationId, inlineOid);
200  add_exact_object_address(&referenced, addrs);
201  }
202 
203  /* dependency on the validator function, if any */
204  if (OidIsValid(valOid))
205  {
206  ObjectAddressSet(referenced, ProcedureRelationId, valOid);
207  add_exact_object_address(&referenced, addrs);
208  }
209 
211  free_object_addresses(addrs);
212 
213  /* Post creation hook for new procedural language */
214  InvokeObjectPostCreateHook(LanguageRelationId, myself.objectId, 0);
215 
217 
218  return myself;
219 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:315
#define NameGetDatum(X)
Definition: postgres.h:595
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define RelationGetDescr(relation)
Definition: rel.h:483
Oid GetUserId(void)
Definition: miscinit.c:476
bool pg_language_ownercheck(Oid lan_oid, Oid roleid)
Definition: aclchk.c:4791
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define PointerGetDatum(X)
Definition: postgres.h:556
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2803
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:272
int errcode(int sqlerrcode)
Definition: elog.c:691
bool superuser(void)
Definition: superuser.c:46
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2594
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:164
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2539
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2835
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:706
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1572
#define LanguageOidIndexId
Definition: pg_language.h:72
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2111
ItemPointerData t_self
Definition: htup.h:65
Definition: c.h:671
#define RowExclusiveLock
Definition: lockdefs.h:38
List * plvalidator
Definition: parsenodes.h:2485
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
char * NameListToString(List *names)
Definition: namespace.c:3101
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
#define BoolGetDatum(X)
Definition: postgres.h:402
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:155
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:800
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:220
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
static Datum values[MAXATTR]
Definition: bootstrap.c:165
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
int errmsg(const char *fmt,...)
Definition: elog.c:902
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

◆ get_language_oid()

Oid get_language_oid ( const char *  langname,
bool  missing_ok 
)

Definition at line 228 of file proclang.c.

References CStringGetDatum, ereport, errcode(), errmsg(), ERROR, GetSysCacheOid1, LANGNAME, and OidIsValid.

Referenced by convert_language_name(), CreateTransform(), get_object_address(), get_object_address_unqualified(), and objectNamesToOids().

229 {
230  Oid oid;
231 
232  oid = GetSysCacheOid1(LANGNAME, Anum_pg_language_oid,
233  CStringGetDatum(langname));
234  if (!OidIsValid(oid) && !missing_ok)
235  ereport(ERROR,
236  (errcode(ERRCODE_UNDEFINED_OBJECT),
237  errmsg("language \"%s\" does not exist", langname)));
238  return oid;
239 }
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition: syscache.h:192
int errcode(int sqlerrcode)
Definition: elog.c:691
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:706
#define ERROR
Definition: elog.h:43
#define CStringGetDatum(X)
Definition: postgres.h:578
#define ereport(elevel,...)
Definition: elog.h:155
int errmsg(const char *fmt,...)
Definition: elog.c:902