PostgreSQL Source Code  git master
proclang.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_language.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_pltemplate.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "commands/proclang.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "parser/parser.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.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.

Data Structures

struct  PLTemplate
 

Functions

static ObjectAddress create_proc_lang (const char *languageName, bool replace, Oid languageOwner, Oid handlerOid, Oid inlineOid, Oid valOid, bool trusted)
 
static PLTemplatefind_language_template (const char *languageName)
 
ObjectAddress CreateProceduralLanguage (CreatePLangStmt *stmt)
 
bool PLTemplateExists (const char *languageName)
 
void DropProceduralLanguageById (Oid langOid)
 
Oid get_language_oid (const char *langname, bool missing_ok)
 

Function Documentation

◆ create_proc_lang()

static ObjectAddress create_proc_lang ( const char *  languageName,
bool  replace,
Oid  languageOwner,
Oid  handlerOid,
Oid  inlineOid,
Oid  valOid,
bool  trusted 
)
static

Definition at line 322 of file proclang.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, BoolGetDatum, CatalogTupleInsert(), CatalogTupleUpdate(), ObjectAddress::classId, deleteDependencyRecordsFor(), DEPENDENCY_NORMAL, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, GetNewOidWithIndex(), GETSTRUCT, heap_form_tuple(), heap_modify_tuple(), HeapTupleIsValid, InvokeObjectPostCreateHook, LANGNAME, LanguageOidIndexId, NameGetDatum, namestrcpy(), OBJECT_LANGUAGE, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, pg_language_ownercheck(), PointerGetDatum, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, table_close(), table_open(), and values.

Referenced by CreateProceduralLanguage().

325 {
326  Relation rel;
327  TupleDesc tupDesc;
328  Datum values[Natts_pg_language];
329  bool nulls[Natts_pg_language];
330  bool replaces[Natts_pg_language];
331  NameData langname;
332  HeapTuple oldtup;
333  HeapTuple tup;
334  Oid langoid;
335  bool is_update;
336  ObjectAddress myself,
337  referenced;
338 
339  rel = table_open(LanguageRelationId, RowExclusiveLock);
340  tupDesc = RelationGetDescr(rel);
341 
342  /* Prepare data to be inserted */
343  memset(values, 0, sizeof(values));
344  memset(nulls, false, sizeof(nulls));
345  memset(replaces, true, sizeof(replaces));
346 
347  namestrcpy(&langname, languageName);
348  values[Anum_pg_language_lanname - 1] = NameGetDatum(&langname);
349  values[Anum_pg_language_lanowner - 1] = ObjectIdGetDatum(languageOwner);
350  values[Anum_pg_language_lanispl - 1] = BoolGetDatum(true);
351  values[Anum_pg_language_lanpltrusted - 1] = BoolGetDatum(trusted);
352  values[Anum_pg_language_lanplcallfoid - 1] = ObjectIdGetDatum(handlerOid);
353  values[Anum_pg_language_laninline - 1] = ObjectIdGetDatum(inlineOid);
354  values[Anum_pg_language_lanvalidator - 1] = ObjectIdGetDatum(valOid);
355  nulls[Anum_pg_language_lanacl - 1] = true;
356 
357  /* Check for pre-existing definition */
358  oldtup = SearchSysCache1(LANGNAME, PointerGetDatum(languageName));
359 
360  if (HeapTupleIsValid(oldtup))
361  {
362  Form_pg_language oldform = (Form_pg_language) GETSTRUCT(oldtup);
363 
364  /* There is one; okay to replace it? */
365  if (!replace)
366  ereport(ERROR,
368  errmsg("language \"%s\" already exists", languageName)));
369  if (!pg_language_ownercheck(oldform->oid, languageOwner))
371  languageName);
372 
373  /*
374  * Do not change existing oid, ownership or permissions. Note
375  * dependency-update code below has to agree with this decision.
376  */
377  replaces[Anum_pg_language_oid - 1] = false;
378  replaces[Anum_pg_language_lanowner - 1] = false;
379  replaces[Anum_pg_language_lanacl - 1] = false;
380 
381  /* Okay, do it... */
382  tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
383  CatalogTupleUpdate(rel, &tup->t_self, tup);
384 
385  langoid = oldform->oid;
386  ReleaseSysCache(oldtup);
387  is_update = true;
388  }
389  else
390  {
391  /* Creating a new language */
392  langoid = GetNewOidWithIndex(rel, LanguageOidIndexId,
393  Anum_pg_language_oid);
394  values[Anum_pg_language_oid - 1] = ObjectIdGetDatum(langoid);
395  tup = heap_form_tuple(tupDesc, values, nulls);
396  CatalogTupleInsert(rel, tup);
397  is_update = false;
398  }
399 
400  /*
401  * Create dependencies for the new language. If we are updating an
402  * existing language, first delete any existing pg_depend entries.
403  * (However, since we are not changing ownership or permissions, the
404  * shared dependencies do *not* need to change, and we leave them alone.)
405  */
406  myself.classId = LanguageRelationId;
407  myself.objectId = langoid;
408  myself.objectSubId = 0;
409 
410  if (is_update)
411  deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
412 
413  /* dependency on owner of language */
414  if (!is_update)
416  languageOwner);
417 
418  /* dependency on extension */
419  recordDependencyOnCurrentExtension(&myself, is_update);
420 
421  /* dependency on the PL handler function */
422  referenced.classId = ProcedureRelationId;
423  referenced.objectId = handlerOid;
424  referenced.objectSubId = 0;
425  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
426 
427  /* dependency on the inline handler function, if any */
428  if (OidIsValid(inlineOid))
429  {
430  referenced.classId = ProcedureRelationId;
431  referenced.objectId = inlineOid;
432  referenced.objectSubId = 0;
433  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
434  }
435 
436  /* dependency on the validator function, if any */
437  if (OidIsValid(valOid))
438  {
439  referenced.classId = ProcedureRelationId;
440  referenced.objectId = valOid;
441  referenced.objectSubId = 0;
442  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
443  }
444 
445  /* Post creation hook for new procedural language */
446  InvokeObjectPostCreateHook(LanguageRelationId, myself.objectId, 0);
447 
449 
450  return myself;
451 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:323
#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:145
#define RelationGetDescr(relation)
Definition: rel.h:442
bool pg_language_ownercheck(Oid lan_oid, Oid roleid)
Definition: aclchk.c:4859
#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:570
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:165
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:638
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3353
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
Definition: c.h:603
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:141
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define BoolGetDatum(X)
Definition: postgres.h:402
#define LanguageOidIndexId
Definition: indexing.h:181
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
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:784
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:33
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183

◆ CreateProceduralLanguage()

ObjectAddress CreateProceduralLanguage ( CreatePLangStmt stmt)

Definition at line 62 of file proclang.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, buildoidvector(), create_proc_lang(), ereport, errcode(), errhint(), errmsg(), ERROR, find_language_template(), get_database_name(), get_func_rettype(), GetUserId(), InvalidOid, LookupFuncName(), MyDatabaseId, NameListToString(), NIL, NOTICE, OBJECT_DATABASE, ObjectAddress::objectId, OidIsValid, pg_database_ownercheck(), CreatePLangStmt::plhandler, CreatePLangStmt::plinline, CreatePLangStmt::plname, CreatePLangStmt::pltrusted, CreatePLangStmt::plvalidator, PointerGetDatum, ProcedureCreate(), CreatePLangStmt::replace, SetFunctionReturnType(), superuser(), SystemFuncName(), PLTemplate::tmpldbacreate, PLTemplate::tmplhandler, PLTemplate::tmplinline, PLTemplate::tmpllibrary, PLTemplate::tmpltrusted, PLTemplate::tmplvalidator, and WARNING.

Referenced by ProcessUtilitySlow().

63 {
64  PLTemplate *pltemplate;
65  ObjectAddress tmpAddr;
66  Oid handlerOid,
67  inlineOid,
68  valOid;
69  Oid funcrettype;
70  Oid funcargtypes[1];
71 
72  /*
73  * If we have template information for the language, ignore the supplied
74  * parameters (if any) and use the template information.
75  */
76  if ((pltemplate = find_language_template(stmt->plname)) != NULL)
77  {
78  List *funcname;
79 
80  /*
81  * Give a notice if we are ignoring supplied parameters.
82  */
83  if (stmt->plhandler)
85  (errmsg("using pg_pltemplate information instead of CREATE LANGUAGE parameters")));
86 
87  /*
88  * Check permission
89  */
90  if (!superuser())
91  {
92  if (!pltemplate->tmpldbacreate)
93  ereport(ERROR,
94  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
95  errmsg("must be superuser to create procedural language \"%s\"",
96  stmt->plname)));
100  }
101 
102  /*
103  * Find or create the handler function, which we force to be in the
104  * pg_catalog schema. If already present, it must have the correct
105  * return type.
106  */
107  funcname = SystemFuncName(pltemplate->tmplhandler);
108  handlerOid = LookupFuncName(funcname, 0, funcargtypes, true);
109  if (OidIsValid(handlerOid))
110  {
111  funcrettype = get_func_rettype(handlerOid);
112  if (funcrettype != LANGUAGE_HANDLEROID)
113  ereport(ERROR,
114  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
115  errmsg("function %s must return type %s",
116  NameListToString(funcname), "language_handler")));
117  }
118  else
119  {
120  tmpAddr = ProcedureCreate(pltemplate->tmplhandler,
121  PG_CATALOG_NAMESPACE,
122  false, /* replace */
123  false, /* returnsSet */
124  LANGUAGE_HANDLEROID,
125  BOOTSTRAP_SUPERUSERID,
126  ClanguageId,
127  F_FMGR_C_VALIDATOR,
128  pltemplate->tmplhandler,
129  pltemplate->tmpllibrary,
130  PROKIND_FUNCTION,
131  false, /* security_definer */
132  false, /* isLeakProof */
133  false, /* isStrict */
134  PROVOLATILE_VOLATILE,
135  PROPARALLEL_UNSAFE,
136  buildoidvector(funcargtypes, 0),
137  PointerGetDatum(NULL),
138  PointerGetDatum(NULL),
139  PointerGetDatum(NULL),
140  NIL,
141  PointerGetDatum(NULL),
142  PointerGetDatum(NULL),
143  InvalidOid,
144  1,
145  0);
146  handlerOid = tmpAddr.objectId;
147  }
148 
149  /*
150  * Likewise for the anonymous block handler, if required; but we don't
151  * care about its return type.
152  */
153  if (pltemplate->tmplinline)
154  {
155  funcname = SystemFuncName(pltemplate->tmplinline);
156  funcargtypes[0] = INTERNALOID;
157  inlineOid = LookupFuncName(funcname, 1, funcargtypes, true);
158  if (!OidIsValid(inlineOid))
159  {
160  tmpAddr = ProcedureCreate(pltemplate->tmplinline,
161  PG_CATALOG_NAMESPACE,
162  false, /* replace */
163  false, /* returnsSet */
164  VOIDOID,
165  BOOTSTRAP_SUPERUSERID,
166  ClanguageId,
167  F_FMGR_C_VALIDATOR,
168  pltemplate->tmplinline,
169  pltemplate->tmpllibrary,
170  PROKIND_FUNCTION,
171  false, /* security_definer */
172  false, /* isLeakProof */
173  true, /* isStrict */
174  PROVOLATILE_VOLATILE,
175  PROPARALLEL_UNSAFE,
176  buildoidvector(funcargtypes, 1),
177  PointerGetDatum(NULL),
178  PointerGetDatum(NULL),
179  PointerGetDatum(NULL),
180  NIL,
181  PointerGetDatum(NULL),
182  PointerGetDatum(NULL),
183  InvalidOid,
184  1,
185  0);
186  inlineOid = tmpAddr.objectId;
187  }
188  }
189  else
190  inlineOid = InvalidOid;
191 
192  /*
193  * Likewise for the validator, if required; but we don't care about
194  * its return type.
195  */
196  if (pltemplate->tmplvalidator)
197  {
198  funcname = SystemFuncName(pltemplate->tmplvalidator);
199  funcargtypes[0] = OIDOID;
200  valOid = LookupFuncName(funcname, 1, funcargtypes, true);
201  if (!OidIsValid(valOid))
202  {
203  tmpAddr = ProcedureCreate(pltemplate->tmplvalidator,
204  PG_CATALOG_NAMESPACE,
205  false, /* replace */
206  false, /* returnsSet */
207  VOIDOID,
208  BOOTSTRAP_SUPERUSERID,
209  ClanguageId,
210  F_FMGR_C_VALIDATOR,
211  pltemplate->tmplvalidator,
212  pltemplate->tmpllibrary,
213  PROKIND_FUNCTION,
214  false, /* security_definer */
215  false, /* isLeakProof */
216  true, /* isStrict */
217  PROVOLATILE_VOLATILE,
218  PROPARALLEL_UNSAFE,
219  buildoidvector(funcargtypes, 1),
220  PointerGetDatum(NULL),
221  PointerGetDatum(NULL),
222  PointerGetDatum(NULL),
223  NIL,
224  PointerGetDatum(NULL),
225  PointerGetDatum(NULL),
226  InvalidOid,
227  1,
228  0);
229  valOid = tmpAddr.objectId;
230  }
231  }
232  else
233  valOid = InvalidOid;
234 
235  /* ok, create it */
236  return create_proc_lang(stmt->plname, stmt->replace, GetUserId(),
237  handlerOid, inlineOid,
238  valOid, pltemplate->tmpltrusted);
239  }
240  else
241  {
242  /*
243  * No template, so use the provided information. If there's no
244  * handler clause, the user is trying to rely on a template that we
245  * don't have, so complain accordingly.
246  */
247  if (!stmt->plhandler)
248  ereport(ERROR,
249  (errcode(ERRCODE_UNDEFINED_OBJECT),
250  errmsg("unsupported language \"%s\"",
251  stmt->plname),
252  errhint("The supported languages are listed in the pg_pltemplate system catalog.")));
253 
254  /*
255  * Check permission
256  */
257  if (!superuser())
258  ereport(ERROR,
259  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
260  errmsg("must be superuser to create custom procedural language")));
261 
262  /*
263  * Lookup the PL handler function and check that it is of the expected
264  * return type
265  */
266  handlerOid = LookupFuncName(stmt->plhandler, 0, funcargtypes, false);
267  funcrettype = get_func_rettype(handlerOid);
268  if (funcrettype != LANGUAGE_HANDLEROID)
269  {
270  /*
271  * We allow OPAQUE just so we can load old dump files. When we
272  * see a handler function declared OPAQUE, change it to
273  * LANGUAGE_HANDLER. (This is probably obsolete and removable?)
274  */
275  if (funcrettype == OPAQUEOID)
276  {
278  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
279  errmsg("changing return type of function %s from %s to %s",
281  "opaque", "language_handler")));
282  SetFunctionReturnType(handlerOid, LANGUAGE_HANDLEROID);
283  }
284  else
285  ereport(ERROR,
286  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
287  errmsg("function %s must return type %s",
288  NameListToString(stmt->plhandler), "language_handler")));
289  }
290 
291  /* validate the inline function */
292  if (stmt->plinline)
293  {
294  funcargtypes[0] = INTERNALOID;
295  inlineOid = LookupFuncName(stmt->plinline, 1, funcargtypes, false);
296  /* return value is ignored, so we don't check the type */
297  }
298  else
299  inlineOid = InvalidOid;
300 
301  /* validate the validator function */
302  if (stmt->plvalidator)
303  {
304  funcargtypes[0] = OIDOID;
305  valOid = LookupFuncName(stmt->plvalidator, 1, funcargtypes, false);
306  /* return value is ignored, so we don't check the type */
307  }
308  else
309  valOid = InvalidOid;
310 
311  /* ok, create it */
312  return create_proc_lang(stmt->plname, stmt->replace, GetUserId(),
313  handlerOid, inlineOid,
314  valOid, stmt->pltrusted);
315  }
316 }
#define NIL
Definition: pg_list.h:65
List * SystemFuncName(char *name)
int errhint(const char *fmt,...)
Definition: elog.c:974
char * tmpllibrary
Definition: proclang.c:50
Oid GetUserId(void)
Definition: miscinit.c:380
#define PointerGetDatum(X)
Definition: postgres.h:556
bool tmpltrusted
Definition: proclang.c:45
ObjectAddress ProcedureCreate(const char *procedureName, Oid procNamespace, bool replace, bool returnsSet, Oid returnType, Oid proowner, Oid languageObjectId, Oid languageValidator, const char *prosrc, const char *probin, char prokind, bool security_definer, bool isLeakProof, bool isStrict, char volatility, char parallel, oidvector *parameterTypes, Datum allParameterTypes, Datum parameterModes, Datum parameterNames, List *parameterDefaults, Datum trftypes, Datum proconfig, Oid prosupport, float4 procost, float4 prorows)
Definition: pg_proc.c:68
int errcode(int sqlerrcode)
Definition: elog.c:570
bool superuser(void)
Definition: superuser.c:47
unsigned int Oid
Definition: postgres_ext.h:31
static ObjectAddress create_proc_lang(const char *languageName, bool replace, Oid languageOwner, Oid handlerOid, Oid inlineOid, Oid valOid, bool trusted)
Definition: proclang.c:322
#define OidIsValid(objectId)
Definition: c.h:638
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1457
char * tmplinline
Definition: proclang.c:48
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3353
#define ERROR
Definition: elog.h:43
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2100
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2099
#define ereport(elevel, rest)
Definition: elog.h:141
bool pg_database_ownercheck(Oid db_oid, Oid roleid)
Definition: aclchk.c:5173
List * plvalidator
Definition: parsenodes.h:2463
bool tmpldbacreate
Definition: proclang.c:46
#define WARNING
Definition: elog.h:40
char * NameListToString(List *names)
Definition: namespace.c:3094
Oid MyDatabaseId
Definition: globals.c:85
void SetFunctionReturnType(Oid funcOid, Oid newRetType)
#define InvalidOid
Definition: postgres_ext.h:36
#define NOTICE
Definition: elog.h:37
oidvector * buildoidvector(const Oid *oids, int n)
Definition: oid.c:167
int errmsg(const char *fmt,...)
Definition: elog.c:784
char * tmplhandler
Definition: proclang.c:47
static PLTemplate * find_language_template(const char *languageName)
Definition: proclang.c:457
Definition: pg_list.h:50
char * tmplvalidator
Definition: proclang.c:49

◆ DropProceduralLanguageById()

void DropProceduralLanguageById ( Oid  langOid)

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

535 {
536  Relation rel;
537  HeapTuple langTup;
538 
539  rel = table_open(LanguageRelationId, RowExclusiveLock);
540 
541  langTup = SearchSysCache1(LANGOID, ObjectIdGetDatum(langOid));
542  if (!HeapTupleIsValid(langTup)) /* should not happen */
543  elog(ERROR, "cache lookup failed for language %u", langOid);
544 
545  CatalogTupleDelete(rel, &langTup->t_self);
546 
547  ReleaseSysCache(langTup);
548 
550 }
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:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:226
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ find_language_template()

static PLTemplate * find_language_template ( const char *  languageName)
static

Definition at line 457 of file proclang.c.

References AccessShareLock, BTEqualStrategyNumber, CStringGetDatum, GETSTRUCT, heap_getattr, HeapTupleIsValid, sort-test::key, palloc0(), PLTemplateNameIndexId, RelationGetDescr, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TextDatumGetCString, PLTemplate::tmpldbacreate, PLTemplate::tmplhandler, PLTemplate::tmplinline, PLTemplate::tmpllibrary, PLTemplate::tmpltrusted, and PLTemplate::tmplvalidator.

Referenced by CreateProceduralLanguage(), and PLTemplateExists().

458 {
459  PLTemplate *result;
460  Relation rel;
461  SysScanDesc scan;
463  HeapTuple tup;
464 
465  rel = table_open(PLTemplateRelationId, AccessShareLock);
466 
467  ScanKeyInit(&key,
468  Anum_pg_pltemplate_tmplname,
469  BTEqualStrategyNumber, F_NAMEEQ,
470  CStringGetDatum(languageName));
471  scan = systable_beginscan(rel, PLTemplateNameIndexId, true,
472  NULL, 1, &key);
473 
474  tup = systable_getnext(scan);
475  if (HeapTupleIsValid(tup))
476  {
478  Datum datum;
479  bool isnull;
480 
481  result = (PLTemplate *) palloc0(sizeof(PLTemplate));
482  result->tmpltrusted = tmpl->tmpltrusted;
483  result->tmpldbacreate = tmpl->tmpldbacreate;
484 
485  /* Remaining fields are variable-width so we need heap_getattr */
486  datum = heap_getattr(tup, Anum_pg_pltemplate_tmplhandler,
487  RelationGetDescr(rel), &isnull);
488  if (!isnull)
489  result->tmplhandler = TextDatumGetCString(datum);
490 
491  datum = heap_getattr(tup, Anum_pg_pltemplate_tmplinline,
492  RelationGetDescr(rel), &isnull);
493  if (!isnull)
494  result->tmplinline = TextDatumGetCString(datum);
495 
496  datum = heap_getattr(tup, Anum_pg_pltemplate_tmplvalidator,
497  RelationGetDescr(rel), &isnull);
498  if (!isnull)
499  result->tmplvalidator = TextDatumGetCString(datum);
500 
501  datum = heap_getattr(tup, Anum_pg_pltemplate_tmpllibrary,
502  RelationGetDescr(rel), &isnull);
503  if (!isnull)
504  result->tmpllibrary = TextDatumGetCString(datum);
505 
506  /* Ignore template if handler or library info is missing */
507  if (!result->tmplhandler || !result->tmpllibrary)
508  result = NULL;
509  }
510  else
511  result = NULL;
512 
513  systable_endscan(scan);
514 
516 
517  return result;
518 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
char * tmpllibrary
Definition: proclang.c:50
#define RelationGetDescr(relation)
Definition: rel.h:442
bool tmpltrusted
Definition: proclang.c:45
#define AccessShareLock
Definition: lockdefs.h:36
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
char * tmplinline
Definition: proclang.c:48
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
FormData_pg_pltemplate * Form_pg_pltemplate
Definition: pg_pltemplate.h:50
#define CStringGetDatum(X)
Definition: postgres.h:578
bool tmpldbacreate
Definition: proclang.c:46
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:84
void * palloc0(Size size)
Definition: mcxt.c:955
uintptr_t Datum
Definition: postgres.h:367
#define PLTemplateNameIndexId
Definition: indexing.h:210
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
char * tmplhandler
Definition: proclang.c:47
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
char * tmplvalidator
Definition: proclang.c:49
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ get_language_oid()

Oid get_language_oid ( const char *  langname,
bool  missing_ok 
)

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

560 {
561  Oid oid;
562 
563  oid = GetSysCacheOid1(LANGNAME, Anum_pg_language_oid,
564  CStringGetDatum(langname));
565  if (!OidIsValid(oid) && !missing_ok)
566  ereport(ERROR,
567  (errcode(ERRCODE_UNDEFINED_OBJECT),
568  errmsg("language \"%s\" does not exist", langname)));
569  return oid;
570 }
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition: syscache.h:192
int errcode(int sqlerrcode)
Definition: elog.c:570
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
#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:784

◆ PLTemplateExists()

bool PLTemplateExists ( const char *  languageName)

Definition at line 525 of file proclang.c.

References find_language_template().

Referenced by CreateFunction(), and ExecuteDoStmt().

526 {
527  return (find_language_template(languageName) != NULL);
528 }
static PLTemplate * find_language_template(const char *languageName)
Definition: proclang.c:457