* 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
#include "postgres.h"
#include "access/htup_details.h"
+#include "access/parallel.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/dependency.h"
* 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 (;;)
*/
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;
* 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);
/*
* 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,
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));
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;
}
/*
(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);
* 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,
* 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);