PostgreSQL Source Code  git master
proclang.h File Reference
Include dependency graph for proclang.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

ObjectAddress CreateProceduralLanguage (CreatePLangStmt *stmt)
 
void DropProceduralLanguageById (Oid langOid)
 
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, Assert, BoolGetDatum, CatalogTupleInsert(), CatalogTupleUpdate(), ObjectAddress::classId, deleteDependencyRecordsFor(), DEPENDENCY_NORMAL, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, get_func_rettype(), GetNewOidWithIndex(), GETSTRUCT, GetUserId(), heap_form_tuple(), heap_modify_tuple(), HeapTupleIsValid, InvalidOid, InvokeObjectPostCreateHook, LANGNAME, LanguageOidIndexId, LookupFuncName(), NameGetDatum, NameListToString(), namestrcpy(), OBJECT_LANGUAGE, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, pg_language_ownercheck(), CreatePLangStmt::plhandler, CreatePLangStmt::plinline, CreatePLangStmt::plname, CreatePLangStmt::pltrusted, CreatePLangStmt::plvalidator, PointerGetDatum, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), RelationGetDescr, ReleaseSysCache(), CreatePLangStmt::replace, RowExclusiveLock, SearchSysCache1(), SetFunctionReturnType(), superuser(), HeapTupleData::t_self, table_close(), table_open(), values, and WARNING.

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 
61  /*
62  * Check permission
63  */
64  if (!superuser())
65  ereport(ERROR,
66  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
67  errmsg("must be superuser to create custom procedural language")));
68 
69  /*
70  * Lookup the PL handler function and check that it is of the expected
71  * return type
72  */
73  Assert(stmt->plhandler);
74  handlerOid = LookupFuncName(stmt->plhandler, 0, NULL, false);
75  funcrettype = get_func_rettype(handlerOid);
76  if (funcrettype != LANGUAGE_HANDLEROID)
77  {
78  /*
79  * We allow OPAQUE just so we can load old dump files. When we see a
80  * handler function declared OPAQUE, change it to LANGUAGE_HANDLER.
81  * (This is probably obsolete and removable?)
82  */
83  if (funcrettype == OPAQUEOID)
84  {
86  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
87  errmsg("changing return type of function %s from %s to %s",
89  "opaque", "language_handler")));
90  SetFunctionReturnType(handlerOid, LANGUAGE_HANDLEROID);
91  }
92  else
93  ereport(ERROR,
94  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
95  errmsg("function %s must return type %s",
96  NameListToString(stmt->plhandler), "language_handler")));
97  }
98 
99  /* validate the inline function */
100  if (stmt->plinline)
101  {
102  funcargtypes[0] = INTERNALOID;
103  inlineOid = LookupFuncName(stmt->plinline, 1, funcargtypes, false);
104  /* return value is ignored, so we don't check the type */
105  }
106  else
107  inlineOid = InvalidOid;
108 
109  /* validate the validator function */
110  if (stmt->plvalidator)
111  {
112  funcargtypes[0] = OIDOID;
113  valOid = LookupFuncName(stmt->plvalidator, 1, funcargtypes, false);
114  /* return value is ignored, so we don't check the type */
115  }
116  else
117  valOid = InvalidOid;
118 
119  /* ok to create it */
120  rel = table_open(LanguageRelationId, RowExclusiveLock);
121  tupDesc = RelationGetDescr(rel);
122 
123  /* Prepare data to be inserted */
124  memset(values, 0, sizeof(values));
125  memset(nulls, false, sizeof(nulls));
126  memset(replaces, true, sizeof(replaces));
127 
128  namestrcpy(&langname, languageName);
129  values[Anum_pg_language_lanname - 1] = NameGetDatum(&langname);
130  values[Anum_pg_language_lanowner - 1] = ObjectIdGetDatum(languageOwner);
131  values[Anum_pg_language_lanispl - 1] = BoolGetDatum(true);
132  values[Anum_pg_language_lanpltrusted - 1] = BoolGetDatum(stmt->pltrusted);
133  values[Anum_pg_language_lanplcallfoid - 1] = ObjectIdGetDatum(handlerOid);
134  values[Anum_pg_language_laninline - 1] = ObjectIdGetDatum(inlineOid);
135  values[Anum_pg_language_lanvalidator - 1] = ObjectIdGetDatum(valOid);
136  nulls[Anum_pg_language_lanacl - 1] = true;
137 
138  /* Check for pre-existing definition */
139  oldtup = SearchSysCache1(LANGNAME, PointerGetDatum(languageName));
140 
141  if (HeapTupleIsValid(oldtup))
142  {
143  Form_pg_language oldform = (Form_pg_language) GETSTRUCT(oldtup);
144 
145  /* There is one; okay to replace it? */
146  if (!stmt->replace)
147  ereport(ERROR,
149  errmsg("language \"%s\" already exists", languageName)));
150 
151  /* This is currently pointless, since we already checked superuser */
152 #ifdef NOT_USED
153  if (!pg_language_ownercheck(oldform->oid, languageOwner))
155  languageName);
156 #endif
157 
158  /*
159  * Do not change existing oid, ownership or permissions. Note
160  * dependency-update code below has to agree with this decision.
161  */
162  replaces[Anum_pg_language_oid - 1] = false;
163  replaces[Anum_pg_language_lanowner - 1] = false;
164  replaces[Anum_pg_language_lanacl - 1] = false;
165 
166  /* Okay, do it... */
167  tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
168  CatalogTupleUpdate(rel, &tup->t_self, tup);
169 
170  langoid = oldform->oid;
171  ReleaseSysCache(oldtup);
172  is_update = true;
173  }
174  else
175  {
176  /* Creating a new language */
177  langoid = GetNewOidWithIndex(rel, LanguageOidIndexId,
178  Anum_pg_language_oid);
179  values[Anum_pg_language_oid - 1] = ObjectIdGetDatum(langoid);
180  tup = heap_form_tuple(tupDesc, values, nulls);
181  CatalogTupleInsert(rel, tup);
182  is_update = false;
183  }
184 
185  /*
186  * Create dependencies for the new language. If we are updating an
187  * existing language, first delete any existing pg_depend entries.
188  * (However, since we are not changing ownership or permissions, the
189  * shared dependencies do *not* need to change, and we leave them alone.)
190  */
191  myself.classId = LanguageRelationId;
192  myself.objectId = langoid;
193  myself.objectSubId = 0;
194 
195  if (is_update)
196  deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
197 
198  /* dependency on owner of language */
199  if (!is_update)
201  languageOwner);
202 
203  /* dependency on extension */
204  recordDependencyOnCurrentExtension(&myself, is_update);
205 
206  /* dependency on the PL handler function */
207  referenced.classId = ProcedureRelationId;
208  referenced.objectId = handlerOid;
209  referenced.objectSubId = 0;
210  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
211 
212  /* dependency on the inline handler function, if any */
213  if (OidIsValid(inlineOid))
214  {
215  referenced.classId = ProcedureRelationId;
216  referenced.objectId = inlineOid;
217  referenced.objectSubId = 0;
218  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
219  }
220 
221  /* dependency on the validator function, if any */
222  if (OidIsValid(valOid))
223  {
224  referenced.classId = ProcedureRelationId;
225  referenced.objectId = valOid;
226  referenced.objectSubId = 0;
227  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
228  }
229 
230  /* Post creation hook for new procedural language */
231  InvokeObjectPostCreateHook(LanguageRelationId, myself.objectId, 0);
232 
234 
235  return myself;
236 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:317
#define NameGetDatum(X)
Definition: postgres.h:595
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define RelationGetDescr(relation)
Definition: rel.h:454
Oid GetUserId(void)
Definition: miscinit.c:378
bool pg_language_ownercheck(Oid lan_oid, Oid roleid)
Definition: aclchk.c:4857
#define PointerGetDatum(X)
Definition: postgres.h:556
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:190
int errcode(int sqlerrcode)
Definition: elog.c:608
bool superuser(void)
Definition: superuser.c:46
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
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
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:250
#define OidIsValid(objectId)
Definition: c.h:644
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1457
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#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:2103
ItemPointerData t_self
Definition: htup.h:65
Definition: c.h:609
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:141
List * plvalidator
Definition: parsenodes.h:2483
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
char * NameListToString(List *names)
Definition: namespace.c:3094
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
void SetFunctionReturnType(Oid funcOid, Oid newRetType)
#define BoolGetDatum(X)
Definition: postgres.h:402
#define InvalidOid
Definition: postgres_ext.h:36
#define LanguageOidIndexId
Definition: indexing.h:181
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:738
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:138
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
static Datum values[MAXATTR]
Definition: bootstrap.c:167
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
int errmsg(const char *fmt,...)
Definition: elog.c:822
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:31
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183

◆ DropProceduralLanguageById()

void DropProceduralLanguageById ( Oid  langOid)

Definition at line 242 of file proclang.c.

References CatalogTupleDelete(), elog, ERROR, HeapTupleIsValid, LANGOID, ObjectIdGetDatum, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by doDeletion().

243 {
244  Relation rel;
245  HeapTuple langTup;
246 
247  rel = table_open(LanguageRelationId, RowExclusiveLock);
248 
249  langTup = SearchSysCache1(LANGOID, ObjectIdGetDatum(langOid));
250  if (!HeapTupleIsValid(langTup)) /* should not happen */
251  elog(ERROR, "cache lookup failed for language %u", langOid);
252 
253  CatalogTupleDelete(rel, &langTup->t_self);
254 
255  ReleaseSysCache(langTup);
256 
258 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:228
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ get_language_oid()

Oid get_language_oid ( const char *  langname,
bool  missing_ok 
)

Definition at line 267 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().

268 {
269  Oid oid;
270 
271  oid = GetSysCacheOid1(LANGNAME, Anum_pg_language_oid,
272  CStringGetDatum(langname));
273  if (!OidIsValid(oid) && !missing_ok)
274  ereport(ERROR,
275  (errcode(ERRCODE_UNDEFINED_OBJECT),
276  errmsg("language \"%s\" does not exist", langname)));
277  return oid;
278 }
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition: syscache.h:192
int errcode(int sqlerrcode)
Definition: elog.c:608
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
#define ERROR
Definition: elog.h:43
#define CStringGetDatum(X)
Definition: postgres.h:578
#define ereport(elevel, rest)
Definition: elog.h:141
int errmsg(const char *fmt,...)
Definition: elog.c:822