Header And Logo

PostgreSQL
| The world's most advanced open source database.

Functions

proclang.h File Reference

#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 CreateProceduralLanguage (CreatePLangStmt *stmt)
void DropProceduralLanguageById (Oid langOid)
bool PLTemplateExists (const char *languageName)
Oid get_language_oid (const char *langname, bool missing_ok)

Function Documentation

Oid CreateProceduralLanguage ( CreatePLangStmt stmt  ) 

Definition at line 64 of file proclang.c.

References ACL_KIND_DATABASE, aclcheck_error(), ACLCHECK_NOT_OWNER, BOOTSTRAP_SUPERUSERID, buildoidvector(), ClanguageId, create_proc_lang(), ereport, errcode(), errhint(), errmsg(), ERROR, find_language_template(), get_database_name(), get_func_rettype(), GetUserId(), LANGUAGE_HANDLEROID, LookupFuncName(), MyDatabaseId, NameListToString(), NIL, NOTICE, NULL, OidIsValid, OPAQUEOID, PG_CATALOG_NAMESPACE, pg_database_ownercheck(), CreatePLangStmt::plhandler, CreatePLangStmt::plinline, CreatePLangStmt::plname, CreatePLangStmt::pltrusted, CreatePLangStmt::plvalidator, PointerGetDatum, ProcedureCreate(), PROVOLATILE_VOLATILE, CreatePLangStmt::replace, SetFunctionReturnType(), superuser(), SystemFuncName(), PLTemplate::tmpldbacreate, PLTemplate::tmplhandler, PLTemplate::tmplinline, PLTemplate::tmpllibrary, PLTemplate::tmpltrusted, PLTemplate::tmplvalidator, VOIDOID, and WARNING.

Referenced by ProcessUtilitySlow().

{
    PLTemplate *pltemplate;
    Oid         handlerOid,
                inlineOid,
                valOid;
    Oid         funcrettype;
    Oid         funcargtypes[1];

    /*
     * If we have template information for the language, ignore the supplied
     * parameters (if any) and use the template information.
     */
    if ((pltemplate = find_language_template(stmt->plname)) != NULL)
    {
        List       *funcname;

        /*
         * Give a notice if we are ignoring supplied parameters.
         */
        if (stmt->plhandler)
            ereport(NOTICE,
                    (errmsg("using pg_pltemplate information instead of CREATE LANGUAGE parameters")));

        /*
         * Check permission
         */
        if (!superuser())
        {
            if (!pltemplate->tmpldbacreate)
                ereport(ERROR,
                        (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                         errmsg("must be superuser to create procedural language \"%s\"",
                                stmt->plname)));
            if (!pg_database_ownercheck(MyDatabaseId, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
                               get_database_name(MyDatabaseId));
        }

        /*
         * Find or create the handler function, which we force to be in the
         * pg_catalog schema.  If already present, it must have the correct
         * return type.
         */
        funcname = SystemFuncName(pltemplate->tmplhandler);
        handlerOid = LookupFuncName(funcname, 0, funcargtypes, true);
        if (OidIsValid(handlerOid))
        {
            funcrettype = get_func_rettype(handlerOid);
            if (funcrettype != LANGUAGE_HANDLEROID)
                ereport(ERROR,
                        (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                  errmsg("function %s must return type \"language_handler\"",
                         NameListToString(funcname))));
        }
        else
        {
            handlerOid = ProcedureCreate(pltemplate->tmplhandler,
                                         PG_CATALOG_NAMESPACE,
                                         false, /* replace */
                                         false, /* returnsSet */
                                         LANGUAGE_HANDLEROID,
                                         BOOTSTRAP_SUPERUSERID,
                                         ClanguageId,
                                         F_FMGR_C_VALIDATOR,
                                         pltemplate->tmplhandler,
                                         pltemplate->tmpllibrary,
                                         false, /* isAgg */
                                         false, /* isWindowFunc */
                                         false, /* security_definer */
                                         false, /* isLeakProof */
                                         false, /* isStrict */
                                         PROVOLATILE_VOLATILE,
                                         buildoidvector(funcargtypes, 0),
                                         PointerGetDatum(NULL),
                                         PointerGetDatum(NULL),
                                         PointerGetDatum(NULL),
                                         NIL,
                                         PointerGetDatum(NULL),
                                         1,
                                         0);
        }

        /*
         * Likewise for the anonymous block handler, if required; but we don't
         * care about its return type.
         */
        if (pltemplate->tmplinline)
        {
            funcname = SystemFuncName(pltemplate->tmplinline);
            funcargtypes[0] = INTERNALOID;
            inlineOid = LookupFuncName(funcname, 1, funcargtypes, true);
            if (!OidIsValid(inlineOid))
            {
                inlineOid = ProcedureCreate(pltemplate->tmplinline,
                                            PG_CATALOG_NAMESPACE,
                                            false,      /* replace */
                                            false,      /* returnsSet */
                                            VOIDOID,
                                            BOOTSTRAP_SUPERUSERID,
                                            ClanguageId,
                                            F_FMGR_C_VALIDATOR,
                                            pltemplate->tmplinline,
                                            pltemplate->tmpllibrary,
                                            false,      /* isAgg */
                                            false,      /* isWindowFunc */
                                            false,      /* security_definer */
                                            false,      /* isLeakProof */
                                            true,       /* isStrict */
                                            PROVOLATILE_VOLATILE,
                                            buildoidvector(funcargtypes, 1),
                                            PointerGetDatum(NULL),
                                            PointerGetDatum(NULL),
                                            PointerGetDatum(NULL),
                                            NIL,
                                            PointerGetDatum(NULL),
                                            1,
                                            0);
            }
        }
        else
            inlineOid = InvalidOid;

        /*
         * Likewise for the validator, if required; but we don't care about
         * its return type.
         */
        if (pltemplate->tmplvalidator)
        {
            funcname = SystemFuncName(pltemplate->tmplvalidator);
            funcargtypes[0] = OIDOID;
            valOid = LookupFuncName(funcname, 1, funcargtypes, true);
            if (!OidIsValid(valOid))
            {
                valOid = ProcedureCreate(pltemplate->tmplvalidator,
                                         PG_CATALOG_NAMESPACE,
                                         false, /* replace */
                                         false, /* returnsSet */
                                         VOIDOID,
                                         BOOTSTRAP_SUPERUSERID,
                                         ClanguageId,
                                         F_FMGR_C_VALIDATOR,
                                         pltemplate->tmplvalidator,
                                         pltemplate->tmpllibrary,
                                         false, /* isAgg */
                                         false, /* isWindowFunc */
                                         false, /* security_definer */
                                         false, /* isLeakProof */
                                         true,  /* isStrict */
                                         PROVOLATILE_VOLATILE,
                                         buildoidvector(funcargtypes, 1),
                                         PointerGetDatum(NULL),
                                         PointerGetDatum(NULL),
                                         PointerGetDatum(NULL),
                                         NIL,
                                         PointerGetDatum(NULL),
                                         1,
                                         0);
            }
        }
        else
            valOid = InvalidOid;

        /* ok, create it */
        return create_proc_lang(stmt->plname, stmt->replace, GetUserId(),
                                handlerOid, inlineOid,
                                valOid, pltemplate->tmpltrusted);
    }
    else
    {
        /*
         * No template, so use the provided information.  If there's no
         * handler clause, the user is trying to rely on a template that we
         * don't have, so complain accordingly.
         */
        if (!stmt->plhandler)
            ereport(ERROR,
                    (errcode(ERRCODE_UNDEFINED_OBJECT),
                     errmsg("unsupported language \"%s\"",
                            stmt->plname),
                     errhint("The supported languages are listed in the pg_pltemplate system catalog.")));

        /*
         * Check permission
         */
        if (!superuser())
            ereport(ERROR,
                    (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                     errmsg("must be superuser to create custom procedural language")));

        /*
         * Lookup the PL handler function and check that it is of the expected
         * return type
         */
        handlerOid = LookupFuncName(stmt->plhandler, 0, funcargtypes, false);
        funcrettype = get_func_rettype(handlerOid);
        if (funcrettype != LANGUAGE_HANDLEROID)
        {
            /*
             * We allow OPAQUE just so we can load old dump files.  When we
             * see a handler function declared OPAQUE, change it to
             * LANGUAGE_HANDLER.  (This is probably obsolete and removable?)
             */
            if (funcrettype == OPAQUEOID)
            {
                ereport(WARNING,
                        (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                         errmsg("changing return type of function %s from \"opaque\" to \"language_handler\"",
                                NameListToString(stmt->plhandler))));
                SetFunctionReturnType(handlerOid, LANGUAGE_HANDLEROID);
            }
            else
                ereport(ERROR,
                        (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                  errmsg("function %s must return type \"language_handler\"",
                         NameListToString(stmt->plhandler))));
        }

        /* validate the inline function */
        if (stmt->plinline)
        {
            funcargtypes[0] = INTERNALOID;
            inlineOid = LookupFuncName(stmt->plinline, 1, funcargtypes, false);
            /* return value is ignored, so we don't check the type */
        }
        else
            inlineOid = InvalidOid;

        /* validate the validator function */
        if (stmt->plvalidator)
        {
            funcargtypes[0] = OIDOID;
            valOid = LookupFuncName(stmt->plvalidator, 1, funcargtypes, false);
            /* return value is ignored, so we don't check the type */
        }
        else
            valOid = InvalidOid;

        /* ok, create it */
        return create_proc_lang(stmt->plname, stmt->replace, GetUserId(),
                                handlerOid, inlineOid,
                                valOid, stmt->pltrusted);
    }
}

void DropProceduralLanguageById ( Oid  langOid  ) 

Definition at line 520 of file proclang.c.

References elog, ERROR, heap_close, heap_open(), HeapTupleIsValid, LANGOID, LanguageRelationId, ObjectIdGetDatum, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1, simple_heap_delete(), and HeapTupleData::t_self.

Referenced by doDeletion().

{
    Relation    rel;
    HeapTuple   langTup;

    rel = heap_open(LanguageRelationId, RowExclusiveLock);

    langTup = SearchSysCache1(LANGOID, ObjectIdGetDatum(langOid));
    if (!HeapTupleIsValid(langTup))     /* should not happen */
        elog(ERROR, "cache lookup failed for language %u", langOid);

    simple_heap_delete(rel, &langTup->t_self);

    ReleaseSysCache(langTup);

    heap_close(rel, RowExclusiveLock);
}

Oid get_language_oid ( const char *  langname,
bool  missing_ok 
)

Definition at line 545 of file proclang.c.

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

Referenced by convert_language_name(), get_object_address_unqualified(), and objectNamesToOids().

{
    Oid         oid;

    oid = GetSysCacheOid1(LANGNAME, CStringGetDatum(langname));
    if (!OidIsValid(oid) && !missing_ok)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("language \"%s\" does not exist", langname)));
    return oid;
}

bool PLTemplateExists ( const char *  languageName  ) 

Definition at line 511 of file proclang.c.

References find_language_template(), and NULL.

Referenced by CreateFunction(), and ExecuteDoStmt().

{
    return (find_language_template(languageName) != NULL);
}