From dc19aaa12f7006441d6dc7b2e2e824e39302aa12 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 16 Oct 2004 21:16:36 +0000
Subject: [PATCH] Give a more user-friendly error message in case where a table
 is created in a schema whose default tablespace has been dropped.

---
 src/backend/commands/tablecmds.c | 42 +++++++++++++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 9e7f1c812e4..c69bf29d832 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.134 2004/10/12 21:54:36 petere Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.135 2004/10/16 21:16:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -168,6 +168,7 @@ static void StoreCatalogInheritance(Oid relationId, List *supers);
 static int	findAttrByName(const char *attributeName, List *schema);
 static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
 static bool needs_toast_table(Relation rel);
+static void check_tablespace_exists(Oid tablespaceId, Oid namespaceId);
 static int transformColumnNameList(Oid relId, List *colList,
 						int16 *attnums, Oid *atttypids);
 static int transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
@@ -337,6 +338,9 @@ DefineRelation(CreateStmt *stmt, char relkind)
 	{
 		tablespaceId = get_namespace_tablespace(namespaceId);
 		/* note no permission check on tablespace in this case */
+		/* check to see that schema's tablespace still exists */
+		if (OidIsValid(tablespaceId))
+			check_tablespace_exists(tablespaceId, namespaceId);
 	}
 
 	/*
@@ -5865,6 +5869,42 @@ needs_toast_table(Relation rel)
 	return (tuple_length > TOAST_TUPLE_THRESHOLD);
 }
 
+/*
+ * Verify that a schema's tablespace still exists
+ *
+ * We need this because DROP TABLESPACE cannot check whether the target
+ * tablespace is the default tablespace for any schemas.  (It could check
+ * in the current database, but that doesn't seem very helpful.)  Subsequent
+ * attempts to create tables in that tablespace will fail.  This code just
+ * exists to ensure that we give a helpful error message.
+ */
+static void
+check_tablespace_exists(Oid tablespaceId, Oid namespaceId)
+{
+	Relation	pg_tablespace;
+	ScanKeyData entry[1];
+	HeapScanDesc scan;
+	HeapTuple	tuple;
+
+	/* There's no syscache for pg_tablespace, so must look the hard way */
+	pg_tablespace = heap_openr(TableSpaceRelationName, AccessShareLock);
+	ScanKeyInit(&entry[0],
+				ObjectIdAttributeNumber,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(tablespaceId));
+	scan = heap_beginscan(pg_tablespace, SnapshotNow, 1, entry);
+	tuple = heap_getnext(scan, ForwardScanDirection);
+	if (!HeapTupleIsValid(tuple))
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_OBJECT),
+				 errmsg("tablespace with OID %u does not exist",
+						tablespaceId),
+				 errdetail("The default tablespace for schema \"%s\" has been dropped.",
+						   get_namespace_name(namespaceId))));
+	heap_endscan(scan);
+	heap_close(pg_tablespace, AccessShareLock);
+}
+
 
 /*
  * This code supports
-- 
GitLab