* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.113 2008/12/04 17:51:26 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.114 2008/12/15 18:09:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* Export the FooIsVisible functions as SQL-callable functions.
+ *
+ * Note: as of Postgres 8.4, these will silently return NULL if called on
+ * a nonexistent object OID, rather than failing. This is to avoid race
+ * condition errors when a query that's scanning a catalog using an MVCC
+ * snapshot uses one of these functions. The underlying IsVisible functions
+ * operate on SnapshotNow semantics and so might see the object as already
+ * gone when it's still visible to the MVCC snapshot. (There is no race
+ * condition in the current coding because we don't accept sinval messages
+ * between the SearchSysCacheExists test and the subsequent lookup.)
*/
Datum
{
Oid oid = PG_GETARG_OID(0);
+ if (!SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(oid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
PG_RETURN_BOOL(RelationIsVisible(oid));
}
{
Oid oid = PG_GETARG_OID(0);
+ if (!SearchSysCacheExists(TYPEOID,
+ ObjectIdGetDatum(oid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
PG_RETURN_BOOL(TypeIsVisible(oid));
}
{
Oid oid = PG_GETARG_OID(0);
+ if (!SearchSysCacheExists(PROCOID,
+ ObjectIdGetDatum(oid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
PG_RETURN_BOOL(FunctionIsVisible(oid));
}
{
Oid oid = PG_GETARG_OID(0);
+ if (!SearchSysCacheExists(OPEROID,
+ ObjectIdGetDatum(oid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
PG_RETURN_BOOL(OperatorIsVisible(oid));
}
{
Oid oid = PG_GETARG_OID(0);
+ if (!SearchSysCacheExists(CLAOID,
+ ObjectIdGetDatum(oid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
PG_RETURN_BOOL(OpclassIsVisible(oid));
}
{
Oid oid = PG_GETARG_OID(0);
+ if (!SearchSysCacheExists(CONVOID,
+ ObjectIdGetDatum(oid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
PG_RETURN_BOOL(ConversionIsVisible(oid));
}
{
Oid oid = PG_GETARG_OID(0);
+ if (!SearchSysCacheExists(TSPARSEROID,
+ ObjectIdGetDatum(oid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
PG_RETURN_BOOL(TSParserIsVisible(oid));
}
{
Oid oid = PG_GETARG_OID(0);
+ if (!SearchSysCacheExists(TSDICTOID,
+ ObjectIdGetDatum(oid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
PG_RETURN_BOOL(TSDictionaryIsVisible(oid));
}
{
Oid oid = PG_GETARG_OID(0);
+ if (!SearchSysCacheExists(TSTEMPLATEOID,
+ ObjectIdGetDatum(oid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
PG_RETURN_BOOL(TSTemplateIsVisible(oid));
}
{
Oid oid = PG_GETARG_OID(0);
+ if (!SearchSysCacheExists(TSCONFIGOID,
+ ObjectIdGetDatum(oid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
PG_RETURN_BOOL(TSConfigIsVisible(oid));
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.142 2008/09/09 18:58:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.143 2008/12/15 18:09:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
- * privilege, false if not.
+ * privilege, false if not. The variants that take a relation OID
+ * return NULL if the OID doesn't exist (rather than failing, as
+ * they did before Postgres 8.4).
*/
/*
roleid = get_roleid_checked(NameStr(*username));
mode = convert_table_priv_string(priv_type_text);
+ if (!SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(tableoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
aclresult = pg_class_aclcheck(tableoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
roleid = GetUserId();
mode = convert_table_priv_string(priv_type_text);
+ if (!SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(tableoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
aclresult = pg_class_aclcheck(tableoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
mode = convert_table_priv_string(priv_type_text);
+ if (!SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(tableoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
aclresult = pg_class_aclcheck(tableoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
* user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
- * privilege, false if not.
+ * privilege, false if not, or NULL if object doesn't exist.
*/
/*
roleid = get_roleid_checked(NameStr(*username));
mode = convert_database_priv_string(priv_type_text);
+ if (!SearchSysCacheExists(DATABASEOID,
+ ObjectIdGetDatum(databaseoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
roleid = GetUserId();
mode = convert_database_priv_string(priv_type_text);
+ if (!SearchSysCacheExists(DATABASEOID,
+ ObjectIdGetDatum(databaseoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
mode = convert_database_priv_string(priv_type_text);
+ if (!SearchSysCacheExists(DATABASEOID,
+ ObjectIdGetDatum(databaseoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
* user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
- * privilege, false if not.
+ * privilege, false if not, or NULL if object doesn't exist.
*/
/*
roleid = get_roleid_checked(NameStr(*username));
mode = convert_function_priv_string(priv_type_text);
+ if (!SearchSysCacheExists(PROCOID,
+ ObjectIdGetDatum(functionoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
roleid = GetUserId();
mode = convert_function_priv_string(priv_type_text);
+ if (!SearchSysCacheExists(PROCOID,
+ ObjectIdGetDatum(functionoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
mode = convert_function_priv_string(priv_type_text);
+ if (!SearchSysCacheExists(PROCOID,
+ ObjectIdGetDatum(functionoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
* user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
- * privilege, false if not.
+ * privilege, false if not, or NULL if object doesn't exist.
*/
/*
roleid = get_roleid_checked(NameStr(*username));
mode = convert_language_priv_string(priv_type_text);
+ if (!SearchSysCacheExists(LANGOID,
+ ObjectIdGetDatum(languageoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
aclresult = pg_language_aclcheck(languageoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
roleid = GetUserId();
mode = convert_language_priv_string(priv_type_text);
+ if (!SearchSysCacheExists(LANGOID,
+ ObjectIdGetDatum(languageoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
aclresult = pg_language_aclcheck(languageoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
mode = convert_language_priv_string(priv_type_text);
+ if (!SearchSysCacheExists(LANGOID,
+ ObjectIdGetDatum(languageoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
aclresult = pg_language_aclcheck(languageoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
* user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
- * privilege, false if not.
+ * privilege, false if not, or NULL if object doesn't exist.
*/
/*
roleid = get_roleid_checked(NameStr(*username));
mode = convert_schema_priv_string(priv_type_text);
+ if (!SearchSysCacheExists(NAMESPACEOID,
+ ObjectIdGetDatum(schemaoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
roleid = GetUserId();
mode = convert_schema_priv_string(priv_type_text);
+ if (!SearchSysCacheExists(NAMESPACEOID,
+ ObjectIdGetDatum(schemaoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
mode = convert_schema_priv_string(priv_type_text);
+ if (!SearchSysCacheExists(NAMESPACEOID,
+ ObjectIdGetDatum(schemaoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);