PostgreSQL Source Code git master
Functions
proclang.h File Reference
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
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

 
Oid  get_language_oid (const char *langname, bool missing_ok)
 

Function Documentation

CreateProceduralLanguage()

ObjectAddress CreateProceduralLanguage ( CreatePLangStmtstmt )

Definition at line 38 of file proclang.c.

39{
40 const char *languageName = stmt->plname;
41 Oid languageOwner = GetUserId();
42 Oid handlerOid,
43 inlineOid,
44 valOid;
45 Oid funcrettype;
46 Oid funcargtypes[1];
47 Relation rel;
48 TupleDesc tupDesc;
49 Datum values[Natts_pg_language];
50 bool nulls[Natts_pg_language];
51 bool replaces[Natts_pg_language];
52 NameData langname;
53 HeapTuple oldtup;
54 HeapTuple tup;
55 Oid langoid;
56 bool is_update;
57 ObjectAddress myself,
58 referenced;
59 ObjectAddresses *addrs;
60
61 /*
62 * Check permission
63 */
64 if (!superuser())
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)
78 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
79 errmsg("function %s must return type %s",
80 NameListToString(stmt->plhandler), "language_handler")));
81
82 /* validate the inline function */
83 if (stmt->plinline)
84 {
85 funcargtypes[0] = INTERNALOID;
86 inlineOid = LookupFuncName(stmt->plinline, 1, funcargtypes, false);
87 /* return value is ignored, so we don't check the type */
88 }
89 else
90 inlineOid = InvalidOid;
91
92 /* validate the validator function */
93 if (stmt->plvalidator)
94 {
95 funcargtypes[0] = OIDOID;
96 valOid = LookupFuncName(stmt->plvalidator, 1, funcargtypes, false);
97 /* return value is ignored, so we don't check the type */
98 }
99 else
100 valOid = InvalidOid;
101
102 /* ok to create it */
103 rel = table_open(LanguageRelationId, RowExclusiveLock);
104 tupDesc = RelationGetDescr(rel);
105
106 /* Prepare data to be inserted */
107 memset(values, 0, sizeof(values));
108 memset(nulls, false, sizeof(nulls));
109 memset(replaces, true, sizeof(replaces));
110
111 namestrcpy(&langname, languageName);
112 values[Anum_pg_language_lanname - 1] = NameGetDatum(&langname);
113 values[Anum_pg_language_lanowner - 1] = ObjectIdGetDatum(languageOwner);
114 values[Anum_pg_language_lanispl - 1] = BoolGetDatum(true);
115 values[Anum_pg_language_lanpltrusted - 1] = BoolGetDatum(stmt->pltrusted);
116 values[Anum_pg_language_lanplcallfoid - 1] = ObjectIdGetDatum(handlerOid);
117 values[Anum_pg_language_laninline - 1] = ObjectIdGetDatum(inlineOid);
118 values[Anum_pg_language_lanvalidator - 1] = ObjectIdGetDatum(valOid);
119 nulls[Anum_pg_language_lanacl - 1] = true;
120
121 /* Check for pre-existing definition */
122 oldtup = SearchSysCache1(LANGNAME, PointerGetDatum(languageName));
123
124 if (HeapTupleIsValid(oldtup))
125 {
126 Form_pg_language oldform = (Form_pg_language) GETSTRUCT(oldtup);
127
128 /* There is one; okay to replace it? */
129 if (!stmt->replace)
132 errmsg("language \"%s\" already exists", languageName)));
133
134 /* This is currently pointless, since we already checked superuser */
135#ifdef NOT_USED
136 if (!object_ownercheck(LanguageRelationId, oldform->oid, languageOwner))
138 languageName);
139#endif
140
141 /*
142 * Do not change existing oid, ownership or permissions. Note
143 * dependency-update code below has to agree with this decision.
144 */
145 replaces[Anum_pg_language_oid - 1] = false;
146 replaces[Anum_pg_language_lanowner - 1] = false;
147 replaces[Anum_pg_language_lanacl - 1] = false;
148
149 /* Okay, do it... */
150 tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
151 CatalogTupleUpdate(rel, &tup->t_self, tup);
152
153 langoid = oldform->oid;
154 ReleaseSysCache(oldtup);
155 is_update = true;
156 }
157 else
158 {
159 /* Creating a new language */
160 langoid = GetNewOidWithIndex(rel, LanguageOidIndexId,
161 Anum_pg_language_oid);
162 values[Anum_pg_language_oid - 1] = ObjectIdGetDatum(langoid);
163 tup = heap_form_tuple(tupDesc, values, nulls);
164 CatalogTupleInsert(rel, tup);
165 is_update = false;
166 }
167
168 /*
169 * Create dependencies for the new language. If we are updating an
170 * existing language, first delete any existing pg_depend entries.
171 * (However, since we are not changing ownership or permissions, the
172 * shared dependencies do *not* need to change, and we leave them alone.)
173 */
174 myself.classId = LanguageRelationId;
175 myself.objectId = langoid;
176 myself.objectSubId = 0;
177
178 if (is_update)
179 deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
180
181 /* dependency on owner of language */
182 if (!is_update)
184 languageOwner);
185
186 /* dependency on extension */
187 recordDependencyOnCurrentExtension(&myself, is_update);
188
189 addrs = new_object_addresses();
190
191 /* dependency on the PL handler function */
192 ObjectAddressSet(referenced, ProcedureRelationId, handlerOid);
193 add_exact_object_address(&referenced, addrs);
194
195 /* dependency on the inline handler function, if any */
196 if (OidIsValid(inlineOid))
197 {
198 ObjectAddressSet(referenced, ProcedureRelationId, inlineOid);
199 add_exact_object_address(&referenced, addrs);
200 }
201
202 /* dependency on the validator function, if any */
203 if (OidIsValid(valOid))
204 {
205 ObjectAddressSet(referenced, ProcedureRelationId, valOid);
206 add_exact_object_address(&referenced, addrs);
207 }
208
211
212 /* Post creation hook for new procedural language */
213 InvokeObjectPostCreateHook(LanguageRelationId, myself.objectId, 0);
214
216
217 return myself;
218}
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2652
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4088
static Datum values[MAXATTR]
Definition: bootstrap.c:153
#define OidIsValid(objectId)
Definition: c.h:774
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:448
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2768
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2559
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2513
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2799
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
Assert(PointerIsAligned(start, uint64))
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
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
#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:1822
Oid GetUserId(void)
Definition: miscinit.c:469
void namestrcpy(Name name, const char *str)
Definition: name.c:233
char * NameListToString(const List *names)
Definition: namespace.c:3664
#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:2269
@ OBJECT_LANGUAGE
Definition: parsenodes.h:2346
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:332
static Datum BoolGetDatum(bool X)
Definition: postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
static Datum NameGetDatum(const NameData *X)
Definition: postgres.h:383
uint64_t Datum
Definition: postgres.h:70
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
#define RelationGetDescr(relation)
Definition: rel.h:540
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
ItemPointerData t_self
Definition: htup.h:65
int32 objectSubId
Definition: objectaddress.h:28
Definition: rel.h:56
Definition: c.h:746
bool superuser(void)
Definition: superuser.c:46
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:220
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 227 of file proclang.c.

228{
229 Oid oid;
230
231 oid = GetSysCacheOid1(LANGNAME, Anum_pg_language_oid,
232 CStringGetDatum(langname));
233 if (!OidIsValid(oid) && !missing_ok)
235 (errcode(ERRCODE_UNDEFINED_OBJECT),
236 errmsg("language \"%s\" does not exist", langname)));
237 return oid;
238}
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:360
#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().

AltStyle によって変換されたページ (->オリジナル) /