index 41e92992deec95301fdda6d51972f090ec5f9b72..ce795a61c5bb1ec82f1989980b8c4a0c76033fae 100644 (file)
@@ -311,19 +311,6 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation)
newRelation->relname)));
}
- if (newRelation->relpersistence == RELPERSISTENCE_TEMP)
- {
- /* TEMP tables are created in our backend-local temp namespace */
- if (newRelation->schemaname)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
- errmsg("temporary tables cannot specify a schema name")));
- /* Initialize temp namespace if first time through */
- if (!OidIsValid(myTempNamespace))
- InitTempTableNamespace();
- return myTempNamespace;
- }
-
if (newRelation->schemaname)
{
/* check for pg_temp alias */
@@ -338,6 +325,13 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation)
namespaceId = get_namespace_oid(newRelation->schemaname, false);
/* we do not check for USAGE rights here! */
}
+ else if (newRelation->relpersistence == RELPERSISTENCE_TEMP)
+ {
+ /* Initialize temp namespace if first time through */
+ if (!OidIsValid(myTempNamespace))
+ InitTempTableNamespace();
+ return myTempNamespace;
+ }
else
{
/* use the default creation namespace */
@@ -389,6 +383,43 @@ RangeVarGetAndCheckCreationNamespace(const RangeVar *newRelation)
return namespaceId;
}
+/*
+ * Adjust the relpersistence for an about-to-be-created relation based on the
+ * creation namespace, and throw an error for invalid combinations.
+ */
+void
+RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid)
+{
+ switch (newRelation->relpersistence)
+ {
+ case RELPERSISTENCE_TEMP:
+ if (!isTempOrToastNamespace(nspid))
+ {
+ if (isAnyTempNamespace(nspid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot create relations in temporary schemas of other sessions")));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot create temporary relation in non-temporary schema")));
+ }
+ break;
+ case RELPERSISTENCE_PERMANENT:
+ if (isTempOrToastNamespace(nspid))
+ newRelation->relpersistence = RELPERSISTENCE_TEMP;
+ else if (isAnyTempNamespace(nspid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot create relations in temporary schemas of other sessions")));
+ break;
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("only temporary relations may be created in temporary schemas")));
+ }
+}
+
/*
* RelnameGetRelid
* Try to resolve an unqualified relation name.
index cfc685b94996f55f7ef7dfeaa9f2cd523c44d2c5..a3a99d28806c0902cb407144a79b03ba01768204 100644 (file)
@@ -431,6 +431,13 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("constraints on foreign tables are not supported")));
+ /*
+ * Look up the namespace in which we are supposed to create the relation,
+ * and check we have permission to create there.
+ */
+ namespaceId = RangeVarGetAndCheckCreationNamespace(stmt->relation);
+ RangeVarAdjustRelationPersistence(stmt->relation, namespaceId);
+
/*
* Security check: disallow creating temp tables from security-restricted
* code. This is needed because calling code might not expect untrusted
@@ -442,12 +449,6 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("cannot create temporary table within security-restricted operation")));
- /*
- * Look up the namespace in which we are supposed to create the relation,
- * and check we have permission to create there.
- */
- namespaceId = RangeVarGetAndCheckCreationNamespace(stmt->relation);
-
/*
* Select tablespace to use. If not specified, use default tablespace
* (which may in turn default to database's default).
index 3f3e0bce34d42dc7391e9f5c238221f482dec0e9..85a7585c6c9ff568fecc9aea62b0af38a437c6fd 100644 (file)
@@ -1610,6 +1610,7 @@ DefineCompositeType(const RangeVar *typevar, List *coldeflist)
* instead of below about a "relation".
*/
typeNamespace = RangeVarGetCreationNamespace(createStmt->relation);
+ RangeVarAdjustRelationPersistence(createStmt->relation, typeNamespace);
old_type_oid =
GetSysCacheOid2(TYPENAMENSP,
CStringGetDatum(createStmt->relation->relname),
index be681e3fd4f9fa24c3b8fe4fc22dd13549e02f03..b23819965869a58af27ac5633cb20af1664228bc 100644 (file)
@@ -97,10 +97,10 @@ isViewOnTempTable_walker(Node *node, void *context)
*---------------------------------------------------------------------
*/
static Oid
-DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace)
+DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace,
+ Oid namespaceId)
{
- Oid viewOid,
- namespaceId;
+ Oid viewOid;
CreateStmt *createStmt = makeNode(CreateStmt);
List *attrList;
ListCell *t;
@@ -160,7 +160,6 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace)
/*
* Check to see if we want to replace an existing view.
*/
- namespaceId = RangeVarGetCreationNamespace(relation);
viewOid = get_relname_relid(relation->relname, namespaceId);
if (OidIsValid(viewOid) && replace)
@@ -417,6 +416,7 @@ DefineView(ViewStmt *stmt, const char *queryString)
{
Query *viewParse;
Oid viewOid;
+ Oid namespaceId;
RangeVar *view;
/*
@@ -480,28 +480,31 @@ DefineView(ViewStmt *stmt, const char *queryString)
"names than columns")));
}
+ /* Unlogged views are not sensible. */
+ if (stmt->view->relpersistence == RELPERSISTENCE_UNLOGGED)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("views cannot be unlogged because they do not have storage")));
+
/*
* If the user didn't explicitly ask for a temporary view, check whether
* we need one implicitly. We allow TEMP to be inserted automatically as
* long as the CREATE command is consistent with that --- no explicit
* schema name.
*/
- view = stmt->view;
+ view = copyObject(stmt->view); /* don't corrupt original command */
if (view->relpersistence == RELPERSISTENCE_PERMANENT
&& isViewOnTempTable(viewParse))
{
- view = copyObject(view); /* don't corrupt original command */
view->relpersistence = RELPERSISTENCE_TEMP;
ereport(NOTICE,
(errmsg("view \"%s\" will be a temporary view",
view->relname)));
}
- /* Unlogged views are not sensible. */
- if (view->relpersistence == RELPERSISTENCE_UNLOGGED)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("views cannot be unlogged because they do not have storage")));
+ /* Might also need to make it temporary if placed in temp schema. */
+ namespaceId = RangeVarGetCreationNamespace(view);
+ RangeVarAdjustRelationPersistence(view, namespaceId);
/*
* Create the view relation
@@ -510,7 +513,7 @@ DefineView(ViewStmt *stmt, const char *queryString)
* aborted.
*/
viewOid = DefineVirtualRelation(view, viewParse->targetList,
- stmt->replace);
+ stmt->replace, namespaceId);
/*
* The relation we have just created is not visible to any other commands
index 2f8deb470c56fb901bb063c4a9287cd8b14b0256..eacd863647d2b09de71670806d8cbe84a93159ce 100644 (file)
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("ON COMMIT can only be used on temporary tables")));
+ /*
+ * Find namespace to create in, check its permissions
+ */
+ intoName = into->rel->relname;
+ namespaceId = RangeVarGetAndCheckCreationNamespace(into->rel);
+ RangeVarAdjustRelationPersistence(into->rel, namespaceId);
+
/*
* Security check: disallow creating temp tables from security-restricted
* code. This is needed because calling code might not expect untrusted
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("cannot create temporary table within security-restricted operation")));
- /*
- * Find namespace to create in, check its permissions
- */
- intoName = into->rel->relname;
- namespaceId = RangeVarGetAndCheckCreationNamespace(into->rel);
-
/*
* Select tablespace to use. If not specified, use default tablespace
* (which may in turn default to database's default).
index d40a963b744e08087028cff43ae51f4313241219..1771fee6478d6ce2f1d3dcbfb712d25c169f70e3 100644 (file)
@@ -162,6 +162,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
* possible.
*/
namespaceid = RangeVarGetAndCheckCreationNamespace(stmt->relation);
+ RangeVarAdjustRelationPersistence(stmt->relation, namespaceid);
/*
* If the relation already exists and the user specified "IF NOT EXISTS",
@@ -374,7 +375,10 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
if (cxt->rel)
snamespaceid = RelationGetNamespace(cxt->rel);
else
+ {
snamespaceid = RangeVarGetCreationNamespace(cxt->relation);
+ RangeVarAdjustRelationPersistence(cxt->relation, snamespaceid);
+ }
snamespace = get_namespace_name(snamespaceid);
sname = ChooseRelationName(cxt->relation->relname,
column->colname,
index 53600969ad7e29ef5875ff3c1feb3edd59e2c822..7e1e194794c2055912a6dcff27777e49235c4158 100644 (file)
@@ -50,6 +50,7 @@ typedef struct OverrideSearchPath
extern Oid RangeVarGetRelid(const RangeVar *relation, bool failOK);
extern Oid RangeVarGetCreationNamespace(const RangeVar *newRelation);
extern Oid RangeVarGetAndCheckCreationNamespace(const RangeVar *newRelation);
+extern void RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid);
extern Oid RelnameGetRelid(const char *relname);
extern bool RelationIsVisible(Oid relid);
index f2c06854d0f8ce54e40737f838b5fc06d79ee226..f9490a3a5506268a8e462f165a2c0530d725c4c1 100644 (file)
@@ -81,11 +81,11 @@ CREATE VIEW temp_view_test.v2 AS SELECT * FROM base_table;
-- should fail
CREATE VIEW temp_view_test.v3_temp AS SELECT * FROM temp_table;
NOTICE: view "v3_temp" will be a temporary view
-ERROR: temporary tables cannot specify a schema name
+ERROR: cannot create temporary relation in non-temporary schema
-- should fail
CREATE SCHEMA test_schema
CREATE TEMP VIEW testview AS SELECT 1;
-ERROR: temporary tables cannot specify a schema name
+ERROR: cannot create temporary relation in non-temporary schema
-- joins: if any of the join relations are temporary, the view
-- should also be temporary
-- should be non-temp