diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index eeb9543027120b0514517926f5b59c17dfce806a..14bf6e3c801834857bac042e38714dab77a86df1 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.61 2001/06/09 23:21:55 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.62 2001/06/12 15:58:34 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,6 +31,12 @@ static const char *getid(const char *s, char *n);
 static bool aclitemeq(const AclItem *a1, const AclItem *a2);
 static bool aclitemgt(const AclItem *a1, const AclItem *a2);
 
+AclMode convert_priv_string(text *priv_type_text);
+bool has_table_privilege_cname_cname(char *username, char *relname, text *priv_type_text);
+bool has_table_privilege_id_cname(Oid usesysid, char *relname, text *priv_type_text);
+bool has_table_privilege_cname_id(char *username, Oid reloid, text *priv_type_text);
+static char *get_Name(text *relin);
+
 #define ACL_IDTYPE_GID_KEYWORD	"group"
 #define ACL_IDTYPE_UID_KEYWORD	"user"
 
@@ -710,3 +716,752 @@ makeAclString(const char *privileges, const char *grantee, char grant_or_revoke)
 	pfree(str.data);
 	return ret;
 }
+
+
+/*
+ * has_table_privilege_tname_tname
+ *		Check user privileges on a relation given
+ *		text usename, text relname, and text priv name.
+ *
+ * RETURNS
+ *		a boolean value
+ *		't' indicating user has the privilege
+ *		'f' indicating user does not have the privilege
+ */
+Datum
+has_table_privilege_tname_tname(PG_FUNCTION_ARGS)
+{
+	text		*username_text;
+	char		*username;
+	text		*relname_text;
+	char		*relname;
+	text		*priv_type_text;
+	bool		result;
+
+	username_text = PG_GETARG_TEXT_P(0);
+	relname_text = PG_GETARG_TEXT_P(1);
+	priv_type_text = PG_GETARG_TEXT_P(2);
+
+	/* 
+	 * Convert username and relname 'text' pattern to null-terminated string
+	 */
+	username = get_Name(username_text);
+	relname = get_Name(relname_text);
+
+	/*
+	 * Make use of has_table_privilege_cname_cname.
+	 * It accepts the arguments we now have.
+	 */
+	result = has_table_privilege_cname_cname(username, relname, priv_type_text);
+
+	PG_RETURN_BOOL(result);
+
+}
+
+
+/*
+ * has_table_privilege_tname_name
+ *		Check user privileges on a relation given
+ *		text usename, name relname, and text priv name.
+ *
+ * RETURNS
+ *		a boolean value
+ *		't' indicating user has the privilege
+ *		'f' indicating user does not have the privilege
+ */
+Datum
+has_table_privilege_tname_name(PG_FUNCTION_ARGS)
+{
+	text		*username_text;
+	char		*username;
+	Name		relname_name;
+	char		*relname;
+	text		*priv_type_text;
+	bool		result;
+
+	username_text = PG_GETARG_TEXT_P(0);
+	relname_name = PG_GETARG_NAME(1);
+	priv_type_text = PG_GETARG_TEXT_P(2);
+
+	/* 
+	 * Convert username 'text' pattern to null-terminated string
+	 */
+	username = get_Name(username_text);
+
+	/* 
+	 * Convert relname 'name' pattern to null-terminated string
+	 */
+	relname = DatumGetCString(DirectFunctionCall1(nameout, PointerGetDatum(relname_name)));
+
+	/*
+	 * Make use of has_table_privilege_cname_cname.
+	 * It accepts the arguments we now have.
+	 */
+	result = has_table_privilege_cname_cname(username, relname, priv_type_text);
+
+	PG_RETURN_BOOL(result);
+
+}
+
+
+/*
+ * has_table_privilege_name_tname
+ *		Check user privileges on a relation given
+ *		name usename, text relname, and text priv name.
+ *
+ * RETURNS
+ *		a boolean value
+ *		't' indicating user has the privilege
+ *		'f' indicating user does not have the privilege
+ */
+Datum
+has_table_privilege_name_tname(PG_FUNCTION_ARGS)
+{
+	Name		username_name;
+	char		*username;
+	text		*relname_text;
+	char		*relname;
+	text		*priv_type_text;
+	bool		result;
+
+	username_name = PG_GETARG_NAME(0);
+	relname_text = PG_GETARG_TEXT_P(1);
+	priv_type_text = PG_GETARG_TEXT_P(2);
+
+	/* 
+	 * Convert username 'name' pattern to null-terminated string
+	 */
+	username = DatumGetCString(DirectFunctionCall1(nameout, PointerGetDatum(username_name)));
+
+	/* 
+	 * Convert relname 'text' pattern to null-terminated string
+	 */
+	relname = get_Name(relname_text);
+
+	/*
+	 * Make use of has_table_privilege_cname_cname.
+	 * It accepts the arguments we now have.
+	 */
+	result = has_table_privilege_cname_cname(username, relname, priv_type_text);
+
+	PG_RETURN_BOOL(result);
+
+}
+
+
+/*
+ * has_table_privilege_name_name
+ *		Check user privileges on a relation given
+ *		name usename, name relname, and text priv name.
+ *
+ * RETURNS
+ *		a boolean value
+ *		't' indicating user has the privilege
+ *		'f' indicating user does not have the privilege
+ */
+Datum
+has_table_privilege_name_name(PG_FUNCTION_ARGS)
+{
+	Name		username_name;
+	char		*username;
+	Name		relname_name;
+	char		*relname;
+	text		*priv_type_text;
+	bool		result;
+
+	username_name = PG_GETARG_NAME(0);
+	relname_name = PG_GETARG_NAME(1);
+	priv_type_text = PG_GETARG_TEXT_P(2);
+
+	/* 
+	 * Convert username and relname 'name' pattern to null-terminated string
+	 */
+	username = DatumGetCString(DirectFunctionCall1(nameout, PointerGetDatum(username_name)));
+	relname = DatumGetCString(DirectFunctionCall1(nameout, PointerGetDatum(relname_name)));
+
+	/*
+	 * Make use of has_table_privilege_cname_cname.
+	 * It accepts the arguments we now have.
+	 */
+	result = has_table_privilege_cname_cname(username, relname, priv_type_text);
+
+	PG_RETURN_BOOL(result);
+
+}
+
+
+/*
+ * has_table_privilege_tname
+ *		Check user privileges on a relation given
+ *		text relname and text priv name.
+ *		current_user is assumed
+ *
+ * RETURNS
+ *		a boolean value
+ *		't' indicating user has the privilege
+ *		'f' indicating user does not have the privilege
+ */
+Datum
+has_table_privilege_tname(PG_FUNCTION_ARGS)
+{
+	Oid			usesysid = (Oid) -1;
+	text		*relname_text;
+	char		*relname;
+	text		*priv_type_text;
+	bool		result;
+
+	relname_text = PG_GETARG_TEXT_P(0);
+	priv_type_text = PG_GETARG_TEXT_P(1);
+
+	usesysid = GetUserId();
+
+	/* 
+	 * Convert relname 'text' pattern to null-terminated string
+	 */
+	relname = get_Name(relname_text);
+
+	/*
+	 * Make use of has_table_privilege_id_cname.
+	 * It accepts the arguments we now have.
+	 */
+	result = has_table_privilege_id_cname(usesysid, relname, priv_type_text);
+
+	PG_RETURN_BOOL(result);
+
+}
+
+/*
+ * has_table_privilege_name
+ *		Check user privileges on a relation given
+ *		name relname and text priv name.
+ *		current_user is assumed
+ *
+ * RETURNS
+ *		a boolean value
+ *		't' indicating user has the privilege
+ *		'f' indicating user does not have the privilege
+ */
+Datum
+has_table_privilege_name(PG_FUNCTION_ARGS)
+{
+	Oid			usesysid = (Oid) -1;
+	Name		relname_name;
+	char		*relname;
+	text		*priv_type_text;
+	bool		result;
+
+	relname_name = PG_GETARG_NAME(0);
+	priv_type_text = PG_GETARG_TEXT_P(1);
+
+	usesysid = GetUserId();
+
+	/* 
+	 * Convert relname 'Name' pattern to null-terminated string
+	 */
+	relname = DatumGetCString(DirectFunctionCall1(nameout, PointerGetDatum(relname_name)));
+
+	/*
+	 * Make use of has_table_privilege_id_cname.
+	 * It accepts the arguments we now have.
+	 */
+	result = has_table_privilege_id_cname(usesysid, relname, priv_type_text);
+
+	PG_RETURN_BOOL(result);
+
+}
+
+
+/*
+ * has_table_privilege_tname_id
+ *		Check user privileges on a relation given
+ *		text usename, rel oid, and text priv name.
+ *
+ * RETURNS
+ *		a boolean value
+ *		't' indicating user has the privilege
+ *		'f' indicating user does not have the privilege
+ */
+Datum
+has_table_privilege_tname_id(PG_FUNCTION_ARGS)
+{
+	text		*username_text;
+	char		*username;
+	Oid			reloid = 0;
+	text		*priv_type_text;
+	bool		result;
+
+	username_text = PG_GETARG_TEXT_P(0);
+	reloid = PG_GETARG_OID(1);
+	priv_type_text = PG_GETARG_TEXT_P(2);
+
+	/* 
+	 * Convert username 'text' pattern to null-terminated string
+	 */
+	username = get_Name(username_text);
+
+	/*
+	 * Make use of has_table_privilege_cname_id.
+	 * It accepts the arguments we now have.
+	 */
+	result = has_table_privilege_cname_id(username, reloid, priv_type_text);
+
+	PG_RETURN_BOOL(result);
+
+}
+
+
+/*
+ * has_table_privilege_name_id
+ *		Check user privileges on a relation given
+ *		name usename, rel oid, and text priv name.
+ *
+ * RETURNS
+ *		a boolean value
+ *		't' indicating user has the privilege
+ *		'f' indicating user does not have the privilege
+ */
+Datum
+has_table_privilege_name_id(PG_FUNCTION_ARGS)
+{
+	Name		username_name;
+	char		*username;
+	Oid			reloid = 0;
+	text		*priv_type_text = NULL;
+	bool		result;
+
+	username_name = PG_GETARG_NAME(0);
+	reloid = PG_GETARG_OID(1);
+	priv_type_text = PG_GETARG_TEXT_P(2);
+
+	/* 
+	 * Convert username 'name' pattern to null-terminated string
+	 */
+	username = DatumGetCString(DirectFunctionCall1(nameout, PointerGetDatum(username_name)));
+
+	/*
+	 * Make use of has_table_privilege_cname_id.
+	 * It accepts the arguments we now have.
+	 */
+	result = has_table_privilege_cname_id(username, reloid, priv_type_text);
+
+	PG_RETURN_BOOL(result);
+
+}
+
+
+/*
+ * has_table_privilege_id
+ *		Check user privileges on a relation given
+ *		rel oid, and text priv name.
+ *		current_user is assumed
+ *
+ * RETURNS
+ *		a boolean value
+ *		't' indicating user has the privilege
+ *		'f' indicating user does not have the privilege
+ */
+Datum
+has_table_privilege_id(PG_FUNCTION_ARGS)
+{
+	char		*username;
+	Oid			reloid = 0;
+	text		*priv_type_text;
+	bool		result;
+
+	reloid = PG_GETARG_OID(0);
+	priv_type_text = PG_GETARG_TEXT_P(1);
+	username = GetUserName(GetUserId());
+
+	/*
+	 * Make use of has_table_privilege_cname_id.
+	 * It accepts the arguments we now have.
+	 */
+	result = has_table_privilege_cname_id(username, reloid, priv_type_text);
+
+	PG_RETURN_BOOL(result);
+
+}
+
+
+/*
+ * has_table_privilege_id_tname
+ *		Check user privileges on a relation given
+ *		usesysid, text relname, and priv name.
+ *
+ * RETURNS
+ *		a boolean value
+ *		't' indicating user has the privilege
+ *		'f' indicating user does not have the privilege
+ */
+Datum
+has_table_privilege_id_tname(PG_FUNCTION_ARGS)
+{
+	Oid			usesysid;
+	text		*relname_text;
+	char		*relname;
+	text		*priv_type_text;
+	bool		result;
+
+	usesysid = PG_GETARG_OID(0);
+	relname_text = PG_GETARG_TEXT_P(1);
+	priv_type_text = PG_GETARG_TEXT_P(2);
+
+	/* 
+	 * Convert relname 'text' pattern to null-terminated string
+	 */
+	relname = get_Name(relname_text);
+
+	/*
+	 * Make use of has_table_privilege_id_cname.
+	 * It accepts the arguments we now have.
+	 */
+	result = has_table_privilege_id_cname(usesysid, relname, priv_type_text);
+
+	PG_RETURN_BOOL(result);
+
+}
+
+
+/*
+ * has_table_privilege_id_name
+ *		Check user privileges on a relation given
+ *		usesysid, name relname, and priv name.
+ *
+ * RETURNS
+ *		a boolean value
+ *		't' indicating user has the privilege
+ *		'f' indicating user does not have the privilege
+ */
+Datum
+has_table_privilege_id_name(PG_FUNCTION_ARGS)
+{
+	Oid			usesysid;
+	Name		relname_name;
+	char		*relname;
+	text		*priv_type_text;
+	bool		result;
+
+	usesysid = PG_GETARG_OID(0);
+	relname_name = PG_GETARG_NAME(1);
+	priv_type_text = PG_GETARG_TEXT_P(2);
+
+	/* 
+	 * Convert relname 'name' pattern to null-terminated string
+	 */
+	relname = DatumGetCString(DirectFunctionCall1(nameout, PointerGetDatum(relname_name)));
+
+	/*
+	 * Make use of has_table_privilege_id_cname.
+	 * It accepts the arguments we now have.
+	 */
+	result = has_table_privilege_id_cname(usesysid, relname, priv_type_text);
+
+	PG_RETURN_BOOL(result);
+
+}
+
+
+/*
+ * has_table_privilege_id_id
+ *		Check user privileges on a relation given
+ *		usesysid, rel oid, and priv name.
+ *
+ * RETURNS
+ *		a boolean value
+ *		't' indicating user has the privilege
+ *		'f' indicating user does not have the privilege
+ */
+Datum
+has_table_privilege_id_id(PG_FUNCTION_ARGS)
+{
+	Oid			usesysid;
+	Oid			reloid;
+	char		*relname;
+	text		*priv_type_text;
+	HeapTuple	tuple;
+	AclMode		mode;
+	int32		result;
+
+
+	usesysid = PG_GETARG_OID(0);
+	reloid = PG_GETARG_OID(1);
+	priv_type_text = PG_GETARG_TEXT_P(2);
+
+	/*
+	 * Lookup relname based on rel oid
+	 */
+	tuple = SearchSysCache(RELOID, ObjectIdGetDatum(reloid), 0, 0, 0);
+	if (!HeapTupleIsValid(tuple)) {
+		elog(ERROR, "has_table_privilege: invalid relation oid %d", (int) reloid);
+	}
+
+	relname = NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname);
+
+	ReleaseSysCache(tuple);
+
+	/* 
+	 * Convert priv_type_text to an AclMode
+	 */
+	mode = convert_priv_string(priv_type_text);
+
+	/* 
+	 * Finally, check for the privilege
+	 */
+	result = pg_aclcheck(relname, usesysid, mode);
+
+	if (result == ACLCHECK_OK) {
+		PG_RETURN_BOOL(TRUE);
+	} else {
+		PG_RETURN_BOOL(FALSE);
+	}
+
+}
+
+/*
+ *		Internal functions.
+ */
+
+/*
+ * convert_priv_string
+ *		Internal function.
+ *		Return mode from priv_type string
+ *
+ * RETURNS
+ *		AclMode
+ */
+
+AclMode
+convert_priv_string(text *priv_type_text)
+{
+	char	*priv_type = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(priv_type_text)));
+
+	/*
+	 * Return mode from priv_type string
+	 */
+	if (strcasecmp(priv_type, "SELECT") == 0)
+		return ACL_SELECT;
+
+	if (strcasecmp(priv_type, "INSERT") == 0)
+		return ACL_INSERT;
+
+	if (strcasecmp(priv_type, "UPDATE") == 0)
+		return ACL_UPDATE;
+
+	if (strcasecmp(priv_type, "DELETE") == 0)
+		return ACL_DELETE;
+
+	if (strcasecmp(priv_type, "RULE") == 0)
+		return ACL_RULE;
+
+	if (strcasecmp(priv_type, "REFERENCES") == 0)
+		return ACL_REFERENCES;
+
+	if (strcasecmp(priv_type, "TRIGGER") == 0)
+		return ACL_TRIGGER;
+
+	elog(ERROR, "has_table_privilege: invalid privilege type %s", priv_type);
+	/*
+	 * We should never get here, but stop the compiler from complaining
+	 */
+	return ACL_NO;
+
+}
+
+/*
+ * has_table_privilege_cname_cname
+ *		Check user privileges on a relation given
+ *		char *usename, char *relname, and text priv name.
+ *
+ * RETURNS
+ *		a boolean value
+ *		't' indicating user has the privilege
+ *		'f' indicating user does not have the privilege
+ */
+bool
+has_table_privilege_cname_cname(char *username, char *relname, text *priv_type_text)
+{
+
+	Oid			usesysid = (Oid) -1;
+	HeapTuple	tuple;
+	bool		result;
+
+	/*
+	 * Lookup userid based on username
+	 */
+
+	tuple = SearchSysCache(SHADOWNAME, NameGetDatum(username), 0, 0, 0);
+	if (!HeapTupleIsValid(tuple)) {
+		elog(ERROR, "has_table_privilege: invalid user name %s", (char *) username);
+	}
+
+	usesysid = (Oid) ((Form_pg_shadow) GETSTRUCT(tuple))->usesysid;
+	ReleaseSysCache(tuple);
+
+	/*
+	 * Make use of has_table_privilege_id_cname.
+	 * It accepts the arguments we now have.
+	 */
+	result = has_table_privilege_id_cname(usesysid, relname, priv_type_text);
+
+	return result;
+
+}
+
+
+/*
+ * has_table_privilege_cname_id
+ *		Check user privileges on a relation given
+ *		char *usename, rel oid, and text priv name.
+ *
+ * RETURNS
+ *		a boolean value
+ *		't' indicating user has the privilege
+ *		'f' indicating user does not have the privilege
+ */
+bool
+has_table_privilege_cname_id(char *username, Oid reloid, text *priv_type_text)
+{
+	Oid			usesysid = (Oid) -1;
+	char		*relname = NULL;
+	HeapTuple	tuple;
+	bool		result;
+
+	/*
+	 * Lookup userid based on username
+	 */
+
+	tuple = SearchSysCache(SHADOWNAME, NameGetDatum(username), 0, 0, 0);
+	if (!HeapTupleIsValid(tuple)) {
+		elog(ERROR, "has_table_privilege: invalid user name %s", (char *) username);
+	}
+
+	usesysid = (Oid) ((Form_pg_shadow) GETSTRUCT(tuple))->usesysid;
+
+	ReleaseSysCache(tuple);
+
+	/*
+	 * Lookup relname based on rel oid
+	 */
+	tuple = SearchSysCache(RELOID, ObjectIdGetDatum(reloid), 0, 0, 0);
+	if (!HeapTupleIsValid(tuple)) {
+		elog(ERROR, "has_table_privilege: invalid relation oid %d", (int) reloid);
+	}
+
+	relname = NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname);
+
+	ReleaseSysCache(tuple);
+
+	/*
+	 * Make use of has_table_privilege_id_cname.
+	 * It accepts the arguments we now have.
+	 */
+	result = has_table_privilege_id_cname(usesysid, relname, priv_type_text);
+
+	return result;
+
+}
+
+
+/*
+ * has_table_privilege_id_cname
+ *		Check user privileges on a relation given
+ *		usesysid, char *relname, and text priv name.
+ *
+ * RETURNS
+ *		a boolean value
+ *		't' indicating user has the privilege
+ *		'f' indicating user does not have the privilege
+ */
+bool
+has_table_privilege_id_cname(Oid usesysid, char *relname, text *priv_type_text)
+{
+
+	HeapTuple	tuple;
+	AclMode		mode;
+	int32		result;
+
+	/*
+	 * Check relname is valid.
+	 * This is needed to deal with the case when usename is a superuser
+	 * in which case pg_aclcheck simply returns ACLCHECK_OK
+	 * without validating relname
+	 */
+	tuple = SearchSysCache(RELNAME, PointerGetDatum(relname), 0, 0, 0);
+
+	if (!HeapTupleIsValid(tuple)) {
+		elog(ERROR, "has_table_privilege: invalid relname %s", relname);
+	}
+	ReleaseSysCache(tuple);
+
+	/* 
+	 * Convert priv_type_text to an AclMode
+	 */
+	mode = convert_priv_string(priv_type_text);
+
+	/* 
+	 * Finally, check for the privilege
+	 */
+	result = pg_aclcheck(relname, usesysid, mode);
+
+	if (result == ACLCHECK_OK) {
+		return TRUE;
+	} else {
+		return FALSE;
+	}
+
+}
+
+
+/*
+ * Given a 'text' relname parameter to a function, extract the actual
+ * relname.  We downcase the name if it's not double-quoted,
+ * and truncate it if it's too long.
+ *
+ * This is a kluge, really --- should be able to write, e.g. nextval(seqrel).
+ */
+static char *
+get_Name(text *relin)
+{
+	char	   *rawname = DatumGetCString(DirectFunctionCall1(textout,
+												PointerGetDatum(relin)));
+	int			rawlen = strlen(rawname);
+	char	   *relname;
+
+	if (rawlen >= 2 &&
+		rawname[0] == '\"' && rawname[rawlen - 1] == '\"')
+	{
+		/* strip off quotes, keep case */
+		rawname[rawlen - 1] = '\0';
+		relname = pstrdup(rawname + 1);
+		pfree(rawname);
+	}
+	else
+	{
+		relname = rawname;
+
+		/*
+		 * It's important that this match the identifier downcasing code
+		 * used by backend/parser/scan.l.
+		 */
+		for (; *rawname; rawname++)
+		{
+			if (isupper((unsigned char) *rawname))
+				*rawname = tolower((unsigned char) *rawname);
+		}
+	}
+
+	/* Truncate name if it's overlength; again, should match scan.l */
+	if (strlen(relname) >= NAMEDATALEN)
+	{
+#ifdef MULTIBYTE
+		int len;
+
+		len = pg_mbcliplen(relname, i, NAMEDATALEN-1);
+		relname[len] = '\0';
+#else
+		relname[NAMEDATALEN-1] = '\0';
+#endif
+	}
+
+	return relname;
+}
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 1208e686920c9d069c2e7cbf254113304a586d9f..cee5017a6950a921c6cd27a9a0ffaa220473eac3 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.189 2001/06/07 00:09:30 momjian Exp $
+ * $Id: pg_proc.h,v 1.190 2001/06/12 15:58:34 momjian Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -2627,6 +2627,35 @@ DESCR("unary plus");
 DATA(insert OID = 1915 (  numeric_uplus	   PGUID 12 f t t t 1 f 1700 "1700" 100 0 0 100  numeric_uplus - ));
 DESCR("unary plus");
 
+DATA(insert OID = 1920 (  has_table_privilege		   PGUID 12 f t f t 3 f 16 "25 25 25" 100 0 0 100	has_table_privilege_tname_tname - ));
+DESCR("user privilege on relation by text username, text relname");
+DATA(insert OID = 1921 (  has_table_privilege		   PGUID 12 f t f t 3 f 16 "25 19 25" 100 0 0 100	has_table_privilege_tname_name - ));
+DESCR("user privilege on relation by text username, name relname");
+DATA(insert OID = 1922 (  has_table_privilege		   PGUID 12 f t f t 3 f 16 "19 25 25" 100 0 0 100	has_table_privilege_name_tname - ));
+DESCR("user privilege on relation by name username, text relname");
+DATA(insert OID = 1923 (  has_table_privilege		   PGUID 12 f t f t 3 f 16 "19 19 25" 100 0 0 100	has_table_privilege_name_name - ));
+DESCR("user privilege on relation by name username, name relname");
+DATA(insert OID = 1924 (  has_table_privilege		   PGUID 12 f t f t 2 f 16 "25 25" 100 0 0 100	has_table_privilege_tname - ));
+DESCR("current user privilege on relation by text relname");
+DATA(insert OID = 1925 (  has_table_privilege		   PGUID 12 f t f t 2 f 16 "19 25" 100 0 0 100	has_table_privilege_name - ));
+DESCR("current user privilege on relation by name relname");
+
+DATA(insert OID = 1926 (  has_table_privilege		   PGUID 12 f t f t 3 f 16 "25 26 25" 100 0 0 100	has_table_privilege_tname_id - ));
+DESCR("user privilege on relation by text username, rel oid");
+DATA(insert OID = 1927 (  has_table_privilege		   PGUID 12 f t f t 3 f 16 "19 26 25" 100 0 0 100	has_table_privilege_name_id - ));
+DESCR("user privilege on relation by text username, rel oid");
+DATA(insert OID = 1928 (  has_table_privilege		   PGUID 12 f t f t 2 f 16 "26 25" 100 0 0 100	has_table_privilege_id - ));
+DESCR("current user privilege on relation by rel oid");
+
+DATA(insert OID = 1929 (  has_table_privilege		   PGUID 12 f t f t 3 f 16 "26 25 25" 100 0 0 100	has_table_privilege_id_tname - ));
+DESCR("user privilege on relation by usesysid, relname");
+DATA(insert OID = 1930 (  has_table_privilege		   PGUID 12 f t f t 3 f 16 "26 19 25" 100 0 0 100	has_table_privilege_id_name - ));
+DESCR("user privilege on relation by usesysid, relname");
+
+DATA(insert OID = 1931 (  has_table_privilege		   PGUID 12 f t f t 3 f 16 "26 26 25" 100 0 0 100	has_table_privilege_id_id - ));
+DESCR("user privilege on relation by usesysid, rel oid");
+
+
 /*
  * prototypes for functions pg_proc.c
  */
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index 1cf751fad13d0c4e7eb6e31292c37ed2487a8991..f03d6e2e1b4f6a7d87ffa2d37635aa3903e71f7f 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: acl.h,v 1.34 2001/06/09 23:21:55 petere Exp $
+ * $Id: acl.h,v 1.35 2001/06/12 15:58:34 momjian Exp $
  *
  * NOTES
  *	  For backward-compatibility purposes we have to allow there
@@ -191,6 +191,22 @@ extern Datum aclcontains(PG_FUNCTION_ARGS);
 extern const char *aclparse(const char *s, AclItem *aip, unsigned *modechg);
 extern char *makeAclString(const char *privileges, const char *grantee, char grant_or_revoke);
 
+extern Datum has_table_privilege_tname_tname(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_tname_name(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_name_tname(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_name_name(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_tname(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_name(PG_FUNCTION_ARGS);
+
+extern Datum has_table_privilege_tname_id(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_name_id(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_id(PG_FUNCTION_ARGS);
+
+extern Datum has_table_privilege_id_tname(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_id_name(PG_FUNCTION_ARGS);
+
+extern Datum has_table_privilege_id_id(PG_FUNCTION_ARGS);
+
 /*
  * prototypes for functions in aclchk.c
  */
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 109d144494a58f6a88a0fe350e13dc35523b2158..ea53e5030391618d78bb5982622de2177639690c 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: builtins.h,v 1.150 2001/06/09 22:16:17 tgl Exp $
+ * $Id: builtins.h,v 1.151 2001/06/12 15:58:34 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,6 +22,24 @@
 /*
  *		Defined in adt/
  */
+
+/* acl.c */
+extern Datum has_table_privilege_tname_tname(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_tname_name(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_name_tname(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_name_name(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_tname(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_name(PG_FUNCTION_ARGS);
+
+extern Datum has_table_privilege_tname_id(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_name_id(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_id(PG_FUNCTION_ARGS);
+
+extern Datum has_table_privilege_id_tname(PG_FUNCTION_ARGS);
+extern Datum has_table_privilege_id_name(PG_FUNCTION_ARGS);
+
+extern Datum has_table_privilege_id_id(PG_FUNCTION_ARGS);
+
 /* bool.c */
 extern Datum boolin(PG_FUNCTION_ARGS);
 extern Datum boolout(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 08e97511ac920601cb4dfa5cd8cd1f226d0407c8..7e6f9f6e2e27d109f90f91ecc60d69819dc65c6c 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -62,6 +62,7 @@ ignore: random
 test: select_into select_distinct select_distinct_on select_implicit select_having subselect union case join aggregates transactions random portals arrays btree_index hash_index
 
 test: privileges
+test: has_table_priv
 test: misc
 
 # ----------
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index afb0090cdade278939c5f1f504afd3abf6ba4abb..d559fdaf35fb11b716cd00aa1d58745ac2806802 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -1,4 +1,4 @@
-# $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.4 2001/05/27 09:59:30 petere Exp $
+# $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.5 2001/06/12 15:58:34 momjian Exp $
 # This should probably be in an order similar to parallel_schedule.
 test: boolean
 test: char
@@ -69,6 +69,7 @@ test: arrays
 test: btree_index
 test: hash_index
 test: privileges
+test: has_table_priv
 test: misc
 test: select_views
 test: alter_table