]> granicus.if.org Git - postgresql/blobdiff - src/backend/catalog/namespace.c
Update copyright for 2016
[postgresql] / src / backend / catalog / namespace.c
index db2bafd4fab770a84e9976516f345a32b5ff2f55..8b105fe62f6ac89800ab8f541daba1bd3097d477 100644 (file)
@@ -9,7 +9,7 @@
  * and implementing search-path-controlled searches.
  *
  *
- * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
@@ -20,7 +20,9 @@
 #include "postgres.h"
 
 #include "access/htup_details.h"
+#include "access/parallel.h"
 #include "access/xact.h"
+#include "access/xlog.h"
 #include "catalog/dependency.h"
 #include "catalog/objectaccess.h"
 #include "catalog/pg_authid.h"
@@ -260,9 +262,9 @@ RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode,
         * with the answer changing under them, or that they already hold some
         * appropriate lock, and therefore return the first answer we get without
         * checking for invalidation messages.  Also, if the requested lock is
-        * already held, LockRelationOid will not AcceptInvalidationMessages,
-        * so we may fail to notice a change.  We could protect against that case
-        * by calling AcceptInvalidationMessages() before beginning this loop, but
+        * already held, LockRelationOid will not AcceptInvalidationMessages, so
+        * we may fail to notice a change.  We could protect against that case by
+        * calling AcceptInvalidationMessages() before beginning this loop, but
         * that would add a significant amount overhead, so for now we don't.
         */
        for (;;)
@@ -629,7 +631,7 @@ RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid)
        switch (newRelation->relpersistence)
        {
                case RELPERSISTENCE_TEMP:
-                       if (!isTempOrToastNamespace(nspid))
+                       if (!isTempOrTempToastNamespace(nspid))
                        {
                                if (isAnyTempNamespace(nspid))
                                        ereport(ERROR,
@@ -642,7 +644,7 @@ RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid)
                        }
                        break;
                case RELPERSISTENCE_PERMANENT:
-                       if (isTempOrToastNamespace(nspid))
+                       if (isTempOrTempToastNamespace(nspid))
                                newRelation->relpersistence = RELPERSISTENCE_TEMP;
                        else if (isAnyTempNamespace(nspid))
                                ereport(ERROR,
@@ -1074,8 +1076,8 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
                 */
                effective_nargs = Max(pronargs, nargs);
                newResult = (FuncCandidateList)
-                       palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
-                                  effective_nargs * sizeof(Oid));
+                       palloc(offsetof(struct _FuncCandidateList, args) +
+                                  effective_nargs * sizeof(Oid));
                newResult->pathpos = pathpos;
                newResult->oid = HeapTupleGetOid(proctup);
                newResult->nargs = effective_nargs;
@@ -1596,7 +1598,8 @@ OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
         * separate palloc for each operator, but profiling revealed that the
         * pallocs used an unreasonably large fraction of parsing time.
         */
-#define SPACE_PER_OP MAXALIGN(sizeof(struct _FuncCandidateList) + sizeof(Oid))
+#define SPACE_PER_OP MAXALIGN(offsetof(struct _FuncCandidateList, args) + \
+                                                         2 * sizeof(Oid))
 
        if (catlist->n_members > 0)
                resultSpace = palloc(catlist->n_members * SPACE_PER_OP);
@@ -2766,24 +2769,13 @@ LookupCreationNamespace(const char *nspname)
 /*
  * Common checks on switching namespaces.
  *
- * We complain if (1) the old and new namespaces are the same, (2) either the
- * old or new namespaces is a temporary schema (or temporary toast schema), or
- * (3) either the old or new namespaces is the TOAST schema.
+ * We complain if either the old or new namespaces is a temporary schema
+ * (or temporary toast schema), or if either the old or new namespaces is the
+ * TOAST schema.
  */
 void
-CheckSetNamespace(Oid oldNspOid, Oid nspOid, Oid classid, Oid objid)
+CheckSetNamespace(Oid oldNspOid, Oid nspOid)
 {
-       if (oldNspOid == nspOid)
-               ereport(ERROR,
-                               (classid == RelationRelationId ?
-                                errcode(ERRCODE_DUPLICATE_TABLE) :
-                                classid == ProcedureRelationId ?
-                                errcode(ERRCODE_DUPLICATE_FUNCTION) :
-                                errcode(ERRCODE_DUPLICATE_OBJECT),
-                                errmsg("%s is already in schema \"%s\"",
-                                               getObjectDescriptionOids(classid, objid),
-                                               get_namespace_name(nspOid))));
-
        /* disallow renaming into or out of temp schemas */
        if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
                ereport(ERROR,
@@ -2934,7 +2926,7 @@ NameListToString(List *names)
                if (IsA(name, String))
                        appendStringInfoString(&string, strVal(name));
                else if (IsA(name, A_Star))
-                       appendStringInfoString(&string, "*");
+                       appendStringInfoChar(&string, '*');
                else
                        elog(ERROR, "unexpected node type in name list: %d",
                                 (int) nodeTag(name));
@@ -2992,11 +2984,11 @@ isTempToastNamespace(Oid namespaceId)
 }
 
 /*
- * isTempOrToastNamespace - is the given namespace my temporary-table
+ * isTempOrTempToastNamespace - is the given namespace my temporary-table
  *             namespace or my temporary-toast-table namespace?
  */
 bool
-isTempOrToastNamespace(Oid namespaceId)
+isTempOrTempToastNamespace(Oid namespaceId)
 {
        if (OidIsValid(myTempNamespace) &&
         (myTempNamespace == namespaceId || myTempToastNamespace == namespaceId))
@@ -3036,7 +3028,7 @@ bool
 isOtherTempNamespace(Oid namespaceId)
 {
        /* If it's my own temp namespace, say "false" */
-       if (isTempOrToastNamespace(namespaceId))
+       if (isTempOrTempToastNamespace(namespaceId))
                return false;
        /* Else, if it's any temp namespace, say "true" */
        return isAnyTempNamespace(namespaceId);
@@ -3144,20 +3136,44 @@ CopyOverrideSearchPath(OverrideSearchPath *path)
 bool
 OverrideSearchPathMatchesCurrent(OverrideSearchPath *path)
 {
-       /* Easiest way to do this is GetOverrideSearchPath() and compare */
-       bool            result;
-       OverrideSearchPath *cur;
+       ListCell   *lc,
+                          *lcp;
 
-       cur = GetOverrideSearchPath(CurrentMemoryContext);
-       if (path->addCatalog == cur->addCatalog &&
-               path->addTemp == cur->addTemp &&
-               equal(path->schemas, cur->schemas))
-               result = true;
-       else
-               result = false;
-       list_free(cur->schemas);
-       pfree(cur);
-       return result;
+       recomputeNamespacePath();
+
+       /* We scan down the activeSearchPath to see if it matches the input. */
+       lc = list_head(activeSearchPath);
+
+       /* If path->addTemp, first item should be my temp namespace. */
+       if (path->addTemp)
+       {
+               if (lc && lfirst_oid(lc) == myTempNamespace)
+                       lc = lnext(lc);
+               else
+                       return false;
+       }
+       /* If path->addCatalog, next item should be pg_catalog. */
+       if (path->addCatalog)
+       {
+               if (lc && lfirst_oid(lc) == PG_CATALOG_NAMESPACE)
+                       lc = lnext(lc);
+               else
+                       return false;
+       }
+       /* We should now be looking at the activeCreationNamespace. */
+       if (activeCreationNamespace != (lc ? lfirst_oid(lc) : InvalidOid))
+               return false;
+       /* The remainder of activeSearchPath should match path->schemas. */
+       foreach(lcp, path->schemas)
+       {
+               if (lc && lfirst_oid(lc) == lfirst_oid(lcp))
+                       lc = lnext(lc);
+               else
+                       return false;
+       }
+       if (lc)
+               return false;
+       return true;
 }
 
 /*
@@ -3620,6 +3636,12 @@ InitTempTableNamespace(void)
                                (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
                                 errmsg("cannot create temporary tables during recovery")));
 
+       /* Parallel workers can't create temporary tables, either. */
+       if (IsParallelWorker())
+               ereport(ERROR,
+                               (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
+                                errmsg("cannot create temporary tables in parallel mode")));
+
        snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
 
        namespaceId = get_namespace_oid(namespaceName, true);
@@ -3683,7 +3705,7 @@ InitTempTableNamespace(void)
  * End-of-transaction cleanup for namespaces.
  */
 void
-AtEOXact_Namespace(bool isCommit)
+AtEOXact_Namespace(bool isCommit, bool parallel)
 {
        /*
         * If we abort the transaction in which a temp namespace was selected,
@@ -3693,7 +3715,7 @@ AtEOXact_Namespace(bool isCommit)
         * at backend shutdown.  (We only want to register the callback once per
         * session, so this is a good place to do it.)
         */
-       if (myTempNamespaceSubID != InvalidSubTransactionId)
+       if (myTempNamespaceSubID != InvalidSubTransactionId && !parallel)
        {
                if (isCommit)
                        before_shmem_exit(RemoveTempRelationsCallback, 0);