ONCOMMIT_NOOP,
(Datum) 0,
false,
- true,
- false);
+ true);
elog(DEBUG4, "relation created with oid %u", id);
}
do_end();
OnCommitAction oncommit,
Datum reloptions,
bool use_user_acl,
- bool allow_system_table_mods,
- bool if_not_exists)
+ bool allow_system_table_mods)
{
Relation pg_class_desc;
Relation new_rel_desc;
CheckAttributeNamesTypes(tupdesc, relkind, allow_system_table_mods);
/*
- * If the relation already exists, it's an error, unless the user
- * specifies "IF NOT EXISTS". In that case, we just print a notice and do
- * nothing further.
+ * This would fail later on anyway, if the relation already exists. But
+ * by catching it here we can emit a nicer error message.
*/
existing_relid = get_relname_relid(relname, relnamespace);
if (existing_relid != InvalidOid)
- {
- if (if_not_exists)
- {
- ereport(NOTICE,
- (errcode(ERRCODE_DUPLICATE_TABLE),
- errmsg("relation \"%s\" already exists, skipping",
- relname)));
- heap_close(pg_class_desc, RowExclusiveLock);
- return InvalidOid;
- }
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_TABLE),
errmsg("relation \"%s\" already exists", relname)));
- }
/*
* Since we are going to create a rowtype as well, also check for
return namespaceId;
}
+/*
+ * RangeVarGetAndCheckCreationNamespace
+ * As RangeVarGetCreationNamespace, but with a permissions check.
+ */
+Oid
+RangeVarGetAndCheckCreationNamespace(const RangeVar *newRelation)
+{
+ Oid namespaceId;
+
+ namespaceId = RangeVarGetCreationNamespace(newRelation);
+
+ /*
+ * Check we have permission to create there. Skip check if bootstrapping,
+ * since permissions machinery may not be working yet.
+ */
+ if (!IsBootstrapProcessingMode())
+ {
+ AclResult aclresult;
+
+ aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
+ ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
+ get_namespace_name(namespaceId));
+ }
+
+ return namespaceId;
+}
+
/*
* RelnameGetRelid
* Try to resolve an unqualified relation name.
ONCOMMIT_NOOP,
reloptions,
false,
- true,
- false);
+ true);
Assert(toast_relid != InvalidOid);
/* make the toast relation visible, else heap_open will fail */
ONCOMMIT_NOOP,
reloptions,
false,
- true,
- false);
+ true);
Assert(OIDNewHeap != InvalidOid);
ReleaseSysCache(tuple);
errmsg("cannot create temporary table within security-restricted operation")));
/*
- * Look up the namespace in which we are supposed to create the relation.
- * Check we have permission to create there. Skip check if bootstrapping,
- * since permissions machinery may not be working yet.
+ * Look up the namespace in which we are supposed to create the relation,
+ * and check we have permission to create there.
*/
- namespaceId = RangeVarGetCreationNamespace(stmt->relation);
-
- if (!IsBootstrapProcessingMode())
- {
- AclResult aclresult;
-
- aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
- ACL_CREATE);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
- get_namespace_name(namespaceId));
- }
+ namespaceId = RangeVarGetAndCheckCreationNamespace(stmt->relation);
/*
* Select tablespace to use. If not specified, use default tablespace
stmt->oncommit,
reloptions,
true,
- allowSystemTableMods,
- stmt->if_not_exists);
-
- /*
- * If heap_create_with_catalog returns InvalidOid, it means that the user
- * specified "IF NOT EXISTS" and the relation already exists. In that
- * case we do nothing further.
- */
- if (relationId == InvalidOid)
- return InvalidOid;
+ allowSystemTableMods);
/* Store inheritance information for new rel. */
StoreCatalogInheritance(relationId, inheritOids);
Oid namespaceId;
Oid tablespaceId;
Datum reloptions;
- AclResult aclresult;
Oid intoRelationId;
TupleDesc tupdesc;
DR_intorel *myState;
* Find namespace to create in, check its permissions
*/
intoName = into->rel->relname;
- namespaceId = RangeVarGetCreationNamespace(into->rel);
-
- aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
- ACL_CREATE);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
- get_namespace_name(namespaceId));
+ namespaceId = RangeVarGetAndCheckCreationNamespace(into->rel);
/*
* Select tablespace to use. If not specified, use default tablespace
into->onCommit,
reloptions,
true,
- allowSystemTableMods,
- false);
+ allowSystemTableMods);
Assert(intoRelationId != InvalidOid);
FreeTupleDesc(tupdesc);
List *result;
List *save_alist;
ListCell *elements;
+ Oid namespaceid;
/*
* We must not scribble on the passed-in CreateStmt, so copy it. (This is
*/
stmt = (CreateStmt *) copyObject(stmt);
+ /*
+ * Look up the creation namespace. This also checks permissions on the
+ * target namespace, so that we throw any permissions error as early as
+ * possible.
+ */
+ namespaceid = RangeVarGetAndCheckCreationNamespace(stmt->relation);
+
+ /*
+ * If the relation already exists and the user specified "IF NOT EXISTS",
+ * bail out with a NOTICE.
+ */
+ if (stmt->if_not_exists)
+ {
+ Oid existing_relid;
+
+ existing_relid = get_relname_relid(stmt->relation->relname,
+ namespaceid);
+ if (existing_relid != InvalidOid)
+ {
+ ereport(NOTICE,
+ (errcode(ERRCODE_DUPLICATE_TABLE),
+ errmsg("relation \"%s\" already exists, skipping",
+ stmt->relation->relname)));
+ return NIL;
+ }
+ }
+
/*
* If the target relation name isn't schema-qualified, make it so. This
* prevents some corner cases in which added-on rewritten commands might
*/
if (stmt->relation->schemaname == NULL
&& stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
- {
- Oid namespaceid = RangeVarGetCreationNamespace(stmt->relation);
-
stmt->relation->schemaname = get_namespace_name(namespaceid);
- }
/* Set up pstate and CreateStmtContext */
pstate = make_parsestate(NULL);
RELKIND_RELATION,
InvalidOid);
- /*
- * If "IF NOT EXISTS" was specified and the relation
- * already exists, do nothing further.
- */
- if (relOid == InvalidOid)
- continue;
-
/*
* Let AlterTableCreateToastTable decide if this one
* needs a secondary relation too.
relOid = DefineRelation((CreateStmt *) stmt,
RELKIND_FOREIGN_TABLE,
InvalidOid);
-
- /*
- * Unless "IF NOT EXISTS" was specified and the
- * relation already exists, create the
- * pg_foreign_table entry.
- */
- if (relOid != InvalidOid)
- CreateForeignTable((CreateForeignTableStmt *) stmt,
- relOid);
+ CreateForeignTable((CreateForeignTableStmt *) stmt,
+ relOid);
}
else
{
OnCommitAction oncommit,
Datum reloptions,
bool use_user_acl,
- bool allow_system_table_mods,
- bool if_not_exists);
+ bool allow_system_table_mods);
extern void heap_drop_with_catalog(Oid relid);
extern Oid RangeVarGetRelid(const RangeVar *relation, bool failOK);
extern Oid RangeVarGetCreationNamespace(const RangeVar *newRelation);
+extern Oid RangeVarGetAndCheckCreationNamespace(const RangeVar *newRelation);
extern Oid RelnameGetRelid(const char *relname);
extern bool RelationIsVisible(Oid relid);