39{
40 const char *languageName =
stmt->plname;
43 inlineOid,
44 valOid;
50 bool nulls[Natts_pg_language];
51 bool replaces[Natts_pg_language];
56 bool is_update;
58 referenced;
60
61 /*
62 * Check permission
63 */
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 */
76 if (funcrettype != LANGUAGE_HANDLEROID)
78 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
79 errmsg(
"function %s must return type %s",
81
82 /* validate the inline function */
84 {
85 funcargtypes[0] = INTERNALOID;
87 /* return value is ignored, so we don't check the type */
88 }
89 else
91
92 /* validate the validator function */
93 if (
stmt->plvalidator)
94 {
95 funcargtypes[0] = OIDOID;
97 /* return value is ignored, so we don't check the type */
98 }
99 else
101
102 /* ok to create it */
105
106 /* Prepare data to be inserted */
108 memset(nulls, false, sizeof(nulls));
109 memset(replaces, true, sizeof(replaces));
110
119 nulls[Anum_pg_language_lanacl - 1] = true;
120
121 /* Check for pre-existing definition */
123
125 {
127
128 /* There is one; okay to replace it? */
132 errmsg(
"language \"%s\" already exists", languageName)));
133
134 /* This is currently pointless, since we already checked superuser */
135#ifdef NOT_USED
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... */
152
153 langoid = oldform->oid;
155 is_update = true;
156 }
157 else
158 {
159 /* Creating a new language */
161 Anum_pg_language_oid);
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;
177
178 if (is_update)
180
181 /* dependency on owner of language */
182 if (!is_update)
184 languageOwner);
185
186 /* dependency on extension */
188
190
191 /* dependency on the PL handler function */
194
195 /* dependency on the inline handler function, if any */
197 {
200 }
201
202 /* dependency on the validator function, if any */
204 {
207 }
208
211
212 /* Post creation hook for new procedural language */
214
216
217 return myself;
218}
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
static Datum values[MAXATTR]
#define OidIsValid(objectId)
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
ObjectAddresses * new_object_addresses(void)
void free_object_addresses(ObjectAddresses *addrs)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
Assert(PointerIsAligned(start, uint64))
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Oid get_func_rettype(Oid funcid)
void namestrcpy(Name name, const char *str)
char * NameListToString(const List *names)
#define InvokeObjectPostCreateHook(classId, objectId, subId)
#define ObjectAddressSet(addr, class_id, object_id)
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
FormData_pg_language * Form_pg_language
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
static Datum PointerGetDatum(const void *X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static Datum NameGetDatum(const NameData *X)
#define RelationGetDescr(relation)
#define ERRCODE_DUPLICATE_OBJECT
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)