diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index b3fe74fe502f22c3ddfb71ba24c9bdb0c954d1be..978309d59eaa56cc466cb33aa2efaaa68439b792 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.340 2006/09/22 16:20:00 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.341 2006/09/28 20:51:41 tgl Exp $ -->
 
  <chapter id="functions">
   <title>Functions and Operators</title>
@@ -338,6 +338,19 @@
    </para>
   </tip>
 
+  <note>
+   <para>
+    If the <replaceable>expression</replaceable> is row-valued, then
+    <literal>IS NULL</> is true when the row expression itself is null
+    or when all the row's fields are null, while
+    <literal>IS NOT NULL</> is true when the row expression itself is non-null
+    and all the row's fields are non-null.
+    This definition conforms to the SQL standard, and is a change from the
+    inconsistent behavior exhibited by <productname>PostgreSQL</productname>
+    versions prior to 8.2.
+   </para>
+  </note>
+
    <para>
     <indexterm>
      <primary>IS DISTINCT FROM</primary>
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 7f341940d67a21c70c93be06eab23c792ce91dbd..7e9e51f13911635d1d4a7c208e040438b3643e86 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.193 2006/07/27 19:52:05 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.194 2006/09/28 20:51:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -119,7 +119,7 @@ static Datum ExecEvalMinMax(MinMaxExprState *minmaxExpr,
 static Datum ExecEvalNullIf(FuncExprState *nullIfExpr,
 			   ExprContext *econtext,
 			   bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalNullTest(GenericExprState *nstate,
+static Datum ExecEvalNullTest(NullTestState *nstate,
 				 ExprContext *econtext,
 				 bool *isNull, ExprDoneCond *isDone);
 static Datum ExecEvalBooleanTest(GenericExprState *bstate,
@@ -1247,8 +1247,7 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
 
 	funcrettype = exprType((Node *) funcexpr->expr);
 
-	returnsTuple = (funcrettype == RECORDOID ||
-					get_typtype(funcrettype) == 'c');
+	returnsTuple = type_is_rowtype(funcrettype);
 
 	/*
 	 * Prepare a resultinfo node for communication.  We always do this even if
@@ -2683,7 +2682,7 @@ ExecEvalNullIf(FuncExprState *nullIfExpr,
  * ----------------------------------------------------------------
  */
 static Datum
-ExecEvalNullTest(GenericExprState *nstate,
+ExecEvalNullTest(NullTestState *nstate,
 				 ExprContext *econtext,
 				 bool *isNull,
 				 ExprDoneCond *isDone)
@@ -2696,28 +2695,77 @@ ExecEvalNullTest(GenericExprState *nstate,
 	if (isDone && *isDone == ExprEndResult)
 		return result;			/* nothing to check */
 
-	switch (ntest->nulltesttype)
+	if (nstate->argisrow && !(*isNull))
 	{
-		case IS_NULL:
-			if (*isNull)
+		HeapTupleHeader tuple;
+		Oid			tupType;
+		int32		tupTypmod;
+		TupleDesc	tupDesc;
+		HeapTupleData tmptup;
+		int			att;
+
+		tuple = DatumGetHeapTupleHeader(result);
+
+		tupType = HeapTupleHeaderGetTypeId(tuple);
+		tupTypmod = HeapTupleHeaderGetTypMod(tuple);
+
+		/* Lookup tupdesc if first time through or if type changes */
+		tupDesc = get_cached_rowtype(tupType, tupTypmod,
+									 &nstate->argdesc, econtext);
+
+		/*
+		 * heap_attisnull needs a HeapTuple not a bare HeapTupleHeader.
+		 */
+		tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
+		tmptup.t_data = tuple;
+
+		for (att = 1; att <= tupDesc->natts; att++)
+		{
+			/* ignore dropped columns */
+			if (tupDesc->attrs[att-1]->attisdropped)
+				continue;
+			if (heap_attisnull(&tmptup, att))
 			{
-				*isNull = false;
-				return BoolGetDatum(true);
+				/* null field disproves IS NOT NULL */
+				if (ntest->nulltesttype == IS_NOT_NULL)
+					return BoolGetDatum(false);
 			}
 			else
-				return BoolGetDatum(false);
-		case IS_NOT_NULL:
-			if (*isNull)
 			{
-				*isNull = false;
-				return BoolGetDatum(false);
+				/* non-null field disproves IS NULL */
+				if (ntest->nulltesttype == IS_NULL)
+					return BoolGetDatum(false);
 			}
-			else
-				return BoolGetDatum(true);
-		default:
-			elog(ERROR, "unrecognized nulltesttype: %d",
-				 (int) ntest->nulltesttype);
-			return (Datum) 0;	/* keep compiler quiet */
+		}
+
+		return BoolGetDatum(true);
+	}
+	else
+	{
+		/* Simple scalar-argument case, or a null rowtype datum */
+		switch (ntest->nulltesttype)
+		{
+			case IS_NULL:
+				if (*isNull)
+				{
+					*isNull = false;
+					return BoolGetDatum(true);
+				}
+				else
+					return BoolGetDatum(false);
+			case IS_NOT_NULL:
+				if (*isNull)
+				{
+					*isNull = false;
+					return BoolGetDatum(false);
+				}
+				else
+					return BoolGetDatum(true);
+			default:
+				elog(ERROR, "unrecognized nulltesttype: %d",
+					 (int) ntest->nulltesttype);
+				return (Datum) 0;	/* keep compiler quiet */
+		}
 	}
 }
 
@@ -3609,11 +3657,13 @@ ExecInitExpr(Expr *node, PlanState *parent)
 		case T_NullTest:
 			{
 				NullTest   *ntest = (NullTest *) node;
-				GenericExprState *gstate = makeNode(GenericExprState);
+				NullTestState *nstate = makeNode(NullTestState);
 
-				gstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalNullTest;
-				gstate->arg = ExecInitExpr(ntest->arg, parent);
-				state = (ExprState *) gstate;
+				nstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalNullTest;
+				nstate->arg = ExecInitExpr(ntest->arg, parent);
+				nstate->argisrow = type_is_rowtype(exprType((Node *) ntest->arg));
+				nstate->argdesc = NULL;
+				state = (ExprState *) nstate;
 			}
 			break;
 		case T_BooleanTest:
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 48b125a774ce813fe8942599b42e2daf1718fde4..99d3147aeb5da80214128732ea733648c28063e3 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.220 2006/09/06 20:40:47 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.221 2006/09/28 20:51:41 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -2099,6 +2099,85 @@ eval_const_expressions_mutator(Node *node,
 		newfselect->resulttypmod = fselect->resulttypmod;
 		return (Node *) newfselect;
 	}
+	if (IsA(node, NullTest))
+	{
+		NullTest   *ntest = (NullTest *) node;
+		NullTest   *newntest;
+		Node	   *arg;
+
+		arg = eval_const_expressions_mutator((Node *) ntest->arg,
+											 context);
+		if (arg && IsA(arg, RowExpr))
+		{
+			RowExpr  *rarg = (RowExpr *) arg;
+			List	*newargs = NIL;
+			ListCell *l;
+
+			/*
+			 * We break ROW(...) IS [NOT] NULL into separate tests on its
+			 * component fields.  This form is usually more efficient to
+			 * evaluate, as well as being more amenable to optimization.
+			 */
+			foreach(l, rarg->args)
+			{
+				Node *relem = (Node *) lfirst(l);
+
+				/*
+				 * A constant field refutes the whole NullTest if it's of
+				 * the wrong nullness; else we can discard it.
+				 */
+				if (relem && IsA(relem, Const))
+				{
+					Const  *carg = (Const *) relem;
+
+					if (carg->constisnull ?
+						(ntest->nulltesttype == IS_NOT_NULL) :
+						(ntest->nulltesttype == IS_NULL))
+						return makeBoolConst(false, false);
+					continue;
+				}
+				newntest = makeNode(NullTest);
+				newntest->arg = (Expr *) relem;
+				newntest->nulltesttype = ntest->nulltesttype;
+				newargs = lappend(newargs, newntest);
+			}
+			/* If all the inputs were constants, result is TRUE */
+			if (newargs == NIL)
+				return makeBoolConst(true, false);
+			/* If only one nonconst input, it's the result */
+			if (list_length(newargs) == 1)
+				return (Node *) linitial(newargs);
+			/* Else we need an AND node */
+			return (Node *) make_andclause(newargs);
+		}
+		if (arg && IsA(arg, Const))
+		{
+			Const  *carg = (Const *) arg;
+			bool	result;
+
+			switch (ntest->nulltesttype)
+			{
+				case IS_NULL:
+					result = carg->constisnull;
+					break;
+				case IS_NOT_NULL:
+					result = !carg->constisnull;
+					break;
+				default:
+					elog(ERROR, "unrecognized nulltesttype: %d",
+						 (int) ntest->nulltesttype);
+					result = false;	/* keep compiler quiet */
+					break;
+			}
+
+			return makeBoolConst(result, false);
+		}
+
+		newntest = makeNode(NullTest);
+		newntest->arg = (Expr *) arg;
+		newntest->nulltesttype = ntest->nulltesttype;
+		return (Node *) newntest;
+	}
 	if (IsA(node, BooleanTest))
 	{
 		BooleanTest *btest = (BooleanTest *) node;
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index 418c7614121b450bacdf7850b562296e575031b4..b909e6d4bf26d50f93b8889b6178e4938a56f626 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.8 2006/08/05 00:21:14 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.9 2006/09/28 20:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,6 +21,7 @@
 #include "executor/executor.h"
 #include "optimizer/clauses.h"
 #include "optimizer/predtest.h"
+#include "parser/parse_expr.h"
 #include "utils/array.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
@@ -931,14 +932,18 @@ predicate_implied_by_simple_clause(Expr *predicate, Node *clause)
 	{
 		Expr	   *nonnullarg = ((NullTest *) predicate)->arg;
 
-		if (is_opclause(clause) &&
-			list_member(((OpExpr *) clause)->args, nonnullarg) &&
-			op_strict(((OpExpr *) clause)->opno))
-			return true;
-		if (is_funcclause(clause) &&
-			list_member(((FuncExpr *) clause)->args, nonnullarg) &&
-			func_strict(((FuncExpr *) clause)->funcid))
-			return true;
+		/* row IS NOT NULL does not act in the simple way we have in mind */
+		if (!type_is_rowtype(exprType((Node *) nonnullarg)))
+		{
+			if (is_opclause(clause) &&
+				list_member(((OpExpr *) clause)->args, nonnullarg) &&
+				op_strict(((OpExpr *) clause)->opno))
+				return true;
+			if (is_funcclause(clause) &&
+				list_member(((FuncExpr *) clause)->args, nonnullarg) &&
+				func_strict(((FuncExpr *) clause)->funcid))
+				return true;
+		}
 		return false;			/* we can't succeed below... */
 	}
 
@@ -978,14 +983,18 @@ predicate_refuted_by_simple_clause(Expr *predicate, Node *clause)
 	{
 		Expr	   *isnullarg = ((NullTest *) predicate)->arg;
 
-		if (is_opclause(clause) &&
-			list_member(((OpExpr *) clause)->args, isnullarg) &&
-			op_strict(((OpExpr *) clause)->opno))
-			return true;
-		if (is_funcclause(clause) &&
-			list_member(((FuncExpr *) clause)->args, isnullarg) &&
-			func_strict(((FuncExpr *) clause)->funcid))
-			return true;
+		/* row IS NULL does not act in the simple way we have in mind */
+		if (!type_is_rowtype(exprType((Node *) isnullarg)))
+		{
+			if (is_opclause(clause) &&
+				list_member(((OpExpr *) clause)->args, isnullarg) &&
+				op_strict(((OpExpr *) clause)->opno))
+				return true;
+			if (is_funcclause(clause) &&
+				list_member(((FuncExpr *) clause)->args, isnullarg) &&
+				func_strict(((FuncExpr *) clause)->funcid))
+				return true;
+		}
 		return false;			/* we can't succeed below... */
 	}
 
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index e0d52887958b89b190054f5e80e465416ab715a1..69a2af46265a29c40863f22dd818b0bfb21d6a2d 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.565 2006/09/03 22:37:05 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.566 2006/09/28 20:51:42 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -94,7 +94,6 @@ static Node *makeStringConst(char *str, TypeName *typename);
 static Node *makeIntConst(int val);
 static Node *makeFloatConst(char *str);
 static Node *makeAConst(Value *v);
-static Node *makeRowNullTest(NullTestType test, RowExpr *row);
 static A_Const *makeBoolAConst(bool state);
 static FuncCall *makeOverlaps(List *largs, List *rargs, int location);
 static void check_qualified_name(List *names);
@@ -7037,53 +7036,33 @@ a_expr:		c_expr									{ $$ = $1; }
 			 *	a ISNULL
 			 *	a NOTNULL
 			 */
-			| a_expr ISNULL
-				{
-					if (IsA($1, RowExpr))
-						$$ = makeRowNullTest(IS_NULL, (RowExpr *) $1);
-					else
-					{
-						NullTest *n = makeNode(NullTest);
-						n->arg = (Expr *) $1;
-						n->nulltesttype = IS_NULL;
-						$$ = (Node *)n;
-					}
-				}
 			| a_expr IS NULL_P
 				{
-					if (IsA($1, RowExpr))
-						$$ = makeRowNullTest(IS_NULL, (RowExpr *) $1);
-					else
-					{
-						NullTest *n = makeNode(NullTest);
-						n->arg = (Expr *) $1;
-						n->nulltesttype = IS_NULL;
-						$$ = (Node *)n;
-					}
+					NullTest *n = makeNode(NullTest);
+					n->arg = (Expr *) $1;
+					n->nulltesttype = IS_NULL;
+					$$ = (Node *)n;
 				}
-			| a_expr NOTNULL
+			| a_expr ISNULL
 				{
-					if (IsA($1, RowExpr))
-						$$ = makeRowNullTest(IS_NOT_NULL, (RowExpr *) $1);
-					else
-					{
-						NullTest *n = makeNode(NullTest);
-						n->arg = (Expr *) $1;
-						n->nulltesttype = IS_NOT_NULL;
-						$$ = (Node *)n;
-					}
+					NullTest *n = makeNode(NullTest);
+					n->arg = (Expr *) $1;
+					n->nulltesttype = IS_NULL;
+					$$ = (Node *)n;
 				}
 			| a_expr IS NOT NULL_P
 				{
-					if (IsA($1, RowExpr))
-						$$ = makeRowNullTest(IS_NOT_NULL, (RowExpr *) $1);
-					else
-					{
-						NullTest *n = makeNode(NullTest);
-						n->arg = (Expr *) $1;
-						n->nulltesttype = IS_NOT_NULL;
-						$$ = (Node *)n;
-					}
+					NullTest *n = makeNode(NullTest);
+					n->arg = (Expr *) $1;
+					n->nulltesttype = IS_NOT_NULL;
+					$$ = (Node *)n;
+				}
+			| a_expr NOTNULL
+				{
+					NullTest *n = makeNode(NullTest);
+					n->arg = (Expr *) $1;
+					n->nulltesttype = IS_NOT_NULL;
+					$$ = (Node *)n;
 				}
 			| row OVERLAPS row
 				{
@@ -9082,43 +9061,6 @@ makeBoolAConst(bool state)
 	return n;
 }
 
-/* makeRowNullTest()
- * Generate separate operator nodes for a single row descriptor test.
- *
- * Eventually this should be eliminated in favor of making the NullTest
- * node type capable of handling it directly.
- */
-static Node *
-makeRowNullTest(NullTestType test, RowExpr *row)
-{
-	Node		*result = NULL;
-	ListCell	*arg;
-
-	foreach(arg, row->args)
-	{
-		NullTest *n;
-
-		n = makeNode(NullTest);
-		n->arg = (Expr *) lfirst(arg);
-		n->nulltesttype = test;
-
-		if (result == NULL)
-			result = (Node *) n;
-		else if (test == IS_NOT_NULL)
-			result = (Node *) makeA_Expr(AEXPR_OR, NIL, result, (Node *)n, -1);
-		else
-			result = (Node *) makeA_Expr(AEXPR_AND, NIL, result, (Node *)n, -1);
-	}
-
-	if (result == NULL)
-	{
-		/* zero-length rows?  Generate constant TRUE or FALSE */
-		result = (Node *) makeBoolAConst(test == IS_NULL);
-	}
-
-	return result;
-}
-
 /* makeOverlaps()
  * Create and populate a FuncCall node to support the OVERLAPS operator.
  */
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 769206e02c825bc82acd219be708ae90734fc308..53e3a5bf552e0e0f78f20044a432ce10d9983cd1 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.136 2006/08/15 22:36:17 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.137 2006/09/28 20:51:42 tgl Exp $
  *
  * NOTES
  *	  Eventually, the index information should go through here, too.
@@ -1716,6 +1716,18 @@ get_typtype(Oid typid)
 		return '\0';
 }
 
+/*
+ * type_is_rowtype
+ *
+ *		Convenience function to determine whether a type OID represents
+ *		a "rowtype" type --- either RECORD or a named composite type.
+ */
+bool
+type_is_rowtype(Oid typid)
+{
+	return (typid == RECORDOID || get_typtype(typid) == 'c');
+}
+
 /*
  * get_typ_typrelid
  *
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 35ee8a20d06c8e83d15934aa7d3ad971a87e183b..5cbe5a542876620199ddc6d822b7f696f870a4a6 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.160 2006/08/25 04:06:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.161 2006/09/28 20:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -705,6 +705,19 @@ typedef struct MinMaxExprState
 	FmgrInfo	cfunc;			/* lookup info for comparison func */
 } MinMaxExprState;
 
+/* ----------------
+ *		NullTestState node
+ * ----------------
+ */
+typedef struct NullTestState
+{
+	ExprState	xprstate;
+	ExprState  *arg;			/* input expression */
+	bool		argisrow;		/* T if input is of a composite type */
+	/* used only if argisrow: */
+	TupleDesc	argdesc;		/* tupdesc for most recent input */
+} NullTestState;
+
 /* ----------------
  *		CoerceToDomainState node
  * ----------------
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index eb31fd2b6e709b47f26cafb184357137b31d21ba..c7abfba91a4726ba5f5eb6415c89cb82e8cc11ea 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.187 2006/08/02 01:59:47 joe Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.188 2006/09/28 20:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -165,6 +165,7 @@ typedef enum NodeTag
 	T_RowCompareExprState,
 	T_CoalesceExprState,
 	T_MinMaxExprState,
+	T_NullTestState,
 	T_CoerceToDomainState,
 	T_DomainConstraintState,
 
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 17c3a894b0b4586486c3ad38f5c6d63ff819724b..c84bab9287e8207881e7333c06d277266a52c868 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.115 2006/07/27 19:52:07 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.116 2006/09/28 20:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -717,9 +717,12 @@ typedef OpExpr NullIfExpr;
  * NullTest
  *
  * NullTest represents the operation of testing a value for NULLness.
- * Currently, we only support scalar input values, but eventually a
- * row-constructor input should be supported.
  * The appropriate test is performed and returned as a boolean Datum.
+ *
+ * NOTE: the semantics of this for rowtype inputs are noticeably different
+ * from the scalar case.  It would probably be a good idea to include an
+ * "argisrow" flag in the struct to reflect that, but for the moment,
+ * we do not do so to avoid forcing an initdb during 8.2beta.
  * ----------------
  */
 
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index ad2d9e30a62025c85d91e427c1f16e8ede66029d..208cba30476db4cc0543858d2a339653afdd6b66 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.105 2006/07/13 17:47:02 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.106 2006/09/28 20:51:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -90,6 +90,7 @@ extern void get_type_io_data(Oid typid,
 extern char get_typstorage(Oid typid);
 extern Node *get_typdefault(Oid typid);
 extern char get_typtype(Oid typid);
+extern bool type_is_rowtype(Oid typid);
 extern Oid	get_typ_typrelid(Oid typid);
 extern Oid	get_element_type(Oid typid);
 extern Oid	get_array_type(Oid typid);