PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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)
 
Oid get_language_oid (const char *langname, bool missing_ok)
 

Function Documentation

◆ CreateProceduralLanguage()

ObjectAddress CreateProceduralLanguage ( CreatePLangStmt stmt)

Definition at line 37 of file proclang.c.

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

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, LookupFuncName(), NameGetDatum(), NameListToString(), namestrcpy(), new_object_addresses(), OBJECT_LANGUAGE, object_ownercheck(), ObjectAddressSet, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, OidIsValid, PointerGetDatum(), record_object_address_dependencies(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), stmt, superuser(), HeapTupleData::t_self, table_close(), table_open(), and values.

Referenced by ProcessUtilitySlow().

◆ get_language_oid()

Oid get_language_oid ( const char *  langname,
bool  missing_ok 
)

Definition at line 226 of file proclang.c.

227{
228 Oid oid;
229
230 oid = GetSysCacheOid1(LANGNAME, Anum_pg_language_oid,
231 CStringGetDatum(langname));
232 if (!OidIsValid(oid) && !missing_ok)
234 (errcode(ERRCODE_UNDEFINED_OBJECT),
235 errmsg("language \"%s\" does not exist", langname)));
236 return oid;
237}
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition: syscache.h:109

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

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