diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 5a6950e0bee0959017cff6b96168e9dc3c66f48d..c9a02814bff2c1114ee8fb71e411bc9a3e23285e 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.40 2002/12/26 22:37:42 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.41 2003/01/09 20:50:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -37,7 +37,7 @@ ExecSubPlan(SubPlanState *node,
 	SubPlan	   *subplan = (SubPlan *) node->xprstate.expr;
 	PlanState  *planstate = node->planstate;
 	SubLinkType subLinkType = subplan->subLinkType;
-	bool		useor = subplan->useor;
+	bool		useOr = subplan->useOr;
 	MemoryContext oldcontext;
 	TupleTableSlot *slot;
 	Datum		result;
@@ -84,7 +84,7 @@ ExecSubPlan(SubPlanState *node,
 	 * For all sublink types except EXPR_SUBLINK, the result is boolean as
 	 * are the results of the combining operators.	We combine results
 	 * within a tuple (if there are multiple columns) using OR semantics
-	 * if "useor" is true, AND semantics if not.  We then combine results
+	 * if "useOr" is true, AND semantics if not.  We then combine results
 	 * across tuples (if the subplan produces more than one) using OR
 	 * semantics for ANY_SUBLINK or AND semantics for ALL_SUBLINK.
 	 * (MULTIEXPR_SUBLINK doesn't allow multiple tuples from the subplan.)
@@ -107,7 +107,7 @@ ExecSubPlan(SubPlanState *node,
 	{
 		HeapTuple	tup = slot->val;
 		TupleDesc	tdesc = slot->ttc_tupleDescriptor;
-		Datum		rowresult = BoolGetDatum(!useor);
+		Datum		rowresult = BoolGetDatum(!useOr);
 		bool		rownull = false;
 		int			col = 1;
 
@@ -212,7 +212,7 @@ ExecSubPlan(SubPlanState *node,
 				rowresult = expresult;
 				rownull = expnull;
 			}
-			else if (useor)
+			else if (useOr)
 			{
 				/* combine within row per OR semantics */
 				if (expnull)
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index c3abcfc9e80eeb9d60b19f837556c465dac5fc1e..4b326b75224eb11fc51770d09bd5d92a08e1f39b 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.233 2002/12/14 00:17:50 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.234 2003/01/09 20:50:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -809,7 +809,8 @@ _copySubLink(SubLink *from)
 	SubLink    *newnode = makeNode(SubLink);
 
 	COPY_SCALAR_FIELD(subLinkType);
-	COPY_SCALAR_FIELD(useor);
+	COPY_SCALAR_FIELD(operIsEquals);
+	COPY_SCALAR_FIELD(useOr);
 	COPY_NODE_FIELD(lefthand);
 	COPY_NODE_FIELD(oper);
 	COPY_NODE_FIELD(subselect);
@@ -826,7 +827,7 @@ _copySubPlan(SubPlan *from)
 	SubPlan    *newnode = makeNode(SubPlan);
 
 	COPY_SCALAR_FIELD(subLinkType);
-	COPY_SCALAR_FIELD(useor);
+	COPY_SCALAR_FIELD(useOr);
 	COPY_NODE_FIELD(oper);
 	COPY_NODE_FIELD(plan);
 	COPY_SCALAR_FIELD(plan_id);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 5fc333df3de8a0d48c793f1c6ff19b8808d55807..affa7f48a881d42ecb8e8e792684a927cba05595 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.177 2002/12/14 00:17:51 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.178 2003/01/09 20:50:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -287,7 +287,8 @@ static bool
 _equalSubLink(SubLink *a, SubLink *b)
 {
 	COMPARE_SCALAR_FIELD(subLinkType);
-	COMPARE_SCALAR_FIELD(useor);
+	COMPARE_SCALAR_FIELD(operIsEquals);
+	COMPARE_SCALAR_FIELD(useOr);
 	COMPARE_NODE_FIELD(lefthand);
 	COMPARE_NODE_FIELD(oper);
 	COMPARE_NODE_FIELD(subselect);
@@ -299,7 +300,7 @@ static bool
 _equalSubPlan(SubPlan *a, SubPlan *b)
 {
 	COMPARE_SCALAR_FIELD(subLinkType);
-	COMPARE_SCALAR_FIELD(useor);
+	COMPARE_SCALAR_FIELD(useOr);
 	COMPARE_NODE_FIELD(oper);
 	/* should compare plans, but have to settle for comparing plan IDs */
 	COMPARE_SCALAR_FIELD(plan_id);
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 97fc9462a27fef92fb71125336efa9a6e65351a2..204c00ad674c36ca2c59c605515ab7d70658dfef 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.190 2002/12/14 00:17:52 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.191 2003/01/09 20:50:50 tgl Exp $
  *
  * NOTES
  *	  Every node type that can appear in stored rules' parsetrees *must*
@@ -658,7 +658,8 @@ _outSubLink(StringInfo str, SubLink *node)
 	WRITE_NODE_TYPE("SUBLINK");
 
 	WRITE_ENUM_FIELD(subLinkType, SubLinkType);
-	WRITE_BOOL_FIELD(useor);
+	WRITE_BOOL_FIELD(operIsEquals);
+	WRITE_BOOL_FIELD(useOr);
 	WRITE_NODE_FIELD(lefthand);
 	WRITE_NODE_FIELD(oper);
 	WRITE_NODE_FIELD(subselect);
@@ -670,7 +671,7 @@ _outSubPlan(StringInfo str, SubPlan *node)
 	WRITE_NODE_TYPE("SUBPLAN");
 
 	WRITE_ENUM_FIELD(subLinkType, SubLinkType);
-	WRITE_BOOL_FIELD(useor);
+	WRITE_BOOL_FIELD(useOr);
 	WRITE_NODE_FIELD(oper);
 	WRITE_NODE_FIELD(plan);
 	WRITE_INT_FIELD(plan_id);
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 9ecd40f2e1d742a9c1dabab1c64725f273797f37..99afc0438c339ed7714eb9013c30dca3becf316b 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.144 2002/12/14 00:17:54 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.145 2003/01/09 20:50:51 tgl Exp $
  *
  * NOTES
  *	  Path and Plan nodes do not have any readfuncs support, because we
@@ -531,7 +531,8 @@ _readSubLink(void)
 	READ_LOCALS(SubLink);
 
 	READ_ENUM_FIELD(subLinkType, SubLinkType);
-	READ_BOOL_FIELD(useor);
+	READ_BOOL_FIELD(operIsEquals);
+	READ_BOOL_FIELD(useOr);
 	READ_NODE_FIELD(lefthand);
 	READ_NODE_FIELD(oper);
 	READ_NODE_FIELD(subselect);
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 840ba975a34e98c4f010cbe7dc591945e4876b28..f8086d9ab6e2b9308b9740b0bfc76c57411ccb1f 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.61 2002/12/14 00:17:55 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.62 2003/01/09 20:50:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -225,7 +225,7 @@ make_subplan(SubLink *slink, List *lefthand)
 	 * Fill in other fields of the SubPlan node.
 	 */
 	node->subLinkType = slink->subLinkType;
-	node->useor = slink->useor;
+	node->useOr = slink->useOr;
 	node->oper = NIL;
 	node->setParam = NIL;
 	node->parParam = NIL;
@@ -283,7 +283,7 @@ make_subplan(SubLink *slink, List *lefthand)
 									 &node->setParam);
 		PlannerInitPlan = lappend(PlannerInitPlan, node);
 		if (length(oper) > 1)
-			result = (Node *) (node->useor ? make_orclause(oper) :
+			result = (Node *) (node->useOr ? make_orclause(oper) :
 							   make_andclause(oper));
 		else
 			result = (Node *) lfirst(oper);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 1809d515461d8e0081481c4ee576c1221a186e6c..7626fe0e449888a4c39dc5b9ecba179cdd58851a 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.391 2003/01/08 00:22:27 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.392 2003/01/09 20:50:51 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -5420,28 +5420,30 @@ opt_interval:
 
 /* Expressions using row descriptors
  * Define row_descriptor to allow yacc to break the reduce/reduce conflict
- *	with singleton expressions. Use SQL99's ROW keyword to allow rows of
- *  one element.
+ * with singleton expressions. Use SQL99's ROW keyword to allow rows of
+ * one element.
  */
 r_expr:  row IN_P select_with_parens
 				{
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = $1;
 					n->oper = (List *) makeSimpleA_Expr(OP, "=", NULL, NULL);
-					n->useor = FALSE;
 					n->subLinkType = ANY_SUBLINK;
+					/* operIsEquals and useOr will be set later */
 					n->subselect = $3;
 					$$ = (Node *)n;
 				}
 			| row NOT IN_P select_with_parens
 				{
+					/* Make an IN node */
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = $1;
-					n->oper = (List *) makeSimpleA_Expr(OP, "<>", NULL, NULL);
-					n->useor = TRUE;
-					n->subLinkType = ALL_SUBLINK;
+					n->oper = (List *) makeSimpleA_Expr(OP, "=", NULL, NULL);
+					n->subLinkType = ANY_SUBLINK;
+					/* operIsEquals and useOr will be set later */
 					n->subselect = $4;
-					$$ = (Node *)n;
+					/* Stick a NOT on top */
+					$$ = (Node *) makeA_Expr(NOT, NIL, NULL, (Node *) n);
 				}
 			| row qual_all_Op sub_type select_with_parens
 			%prec Op
@@ -5449,11 +5451,8 @@ r_expr:  row IN_P select_with_parens
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = $1;
 					n->oper = (List *) makeA_Expr(OP, $2, NULL, NULL);
-					if (strcmp(strVal(llast($2)), "<>") == 0)
-						n->useor = TRUE;
-					else
-						n->useor = FALSE;
 					n->subLinkType = $3;
+					/* operIsEquals and useOr will be set later */
 					n->subselect = $4;
 					$$ = (Node *)n;
 				}
@@ -5463,11 +5462,8 @@ r_expr:  row IN_P select_with_parens
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = $1;
 					n->oper = (List *) makeA_Expr(OP, $2, NULL, NULL);
-					if (strcmp(strVal(llast($2)), "<>") == 0)
-						n->useor = TRUE;
-					else
-						n->useor = FALSE;
 					n->subLinkType = MULTIEXPR_SUBLINK;
+					/* operIsEquals and useOr will be set later */
 					n->subselect = $3;
 					$$ = (Node *)n;
 				}
@@ -5850,8 +5846,8 @@ a_expr:		c_expr									{ $$ = $1; }
 							SubLink *n = (SubLink *)$3;
 							n->lefthand = makeList1($1);
 							n->oper = (List *) makeSimpleA_Expr(OP, "=", NULL, NULL);
-							n->useor = FALSE;
 							n->subLinkType = ANY_SUBLINK;
+							/* operIsEquals and useOr will be set later */
 							$$ = (Node *)n;
 					}
 					else
@@ -5875,12 +5871,14 @@ a_expr:		c_expr									{ $$ = $1; }
 					/* in_expr returns a SubLink or a list of a_exprs */
 					if (IsA($4, SubLink))
 					{
+						/* Make an IN node */
 						SubLink *n = (SubLink *)$4;
 						n->lefthand = makeList1($1);
-						n->oper = (List *) makeSimpleA_Expr(OP, "<>", NULL, NULL);
-						n->useor = FALSE;
-						n->subLinkType = ALL_SUBLINK;
-						$$ = (Node *)n;
+						n->oper = (List *) makeSimpleA_Expr(OP, "=", NULL, NULL);
+						n->subLinkType = ANY_SUBLINK;
+						/* operIsEquals and useOr will be set later */
+						/* Stick a NOT on top */
+						$$ = (Node *) makeA_Expr(NOT, NIL, NULL, (Node *) n);
 					}
 					else
 					{
@@ -5903,8 +5901,8 @@ a_expr:		c_expr									{ $$ = $1; }
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = makeList1($1);
 					n->oper = (List *) makeA_Expr(OP, $2, NULL, NULL);
-					n->useor = FALSE; /* doesn't matter since only one col */
 					n->subLinkType = $3;
+					/* operIsEquals and useOr will be set later */
 					n->subselect = $4;
 					$$ = (Node *)n;
 				}
@@ -6447,7 +6445,6 @@ c_expr:		columnref								{ $$ = (Node *) $1; }
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = NIL;
 					n->oper = NIL;
-					n->useor = FALSE;
 					n->subLinkType = EXPR_SUBLINK;
 					n->subselect = $1;
 					$$ = (Node *)n;
@@ -6457,7 +6454,6 @@ c_expr:		columnref								{ $$ = (Node *) $1; }
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = NIL;
 					n->oper = NIL;
-					n->useor = FALSE;
 					n->subLinkType = EXISTS_SUBLINK;
 					n->subselect = $2;
 					$$ = (Node *)n;
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 9705ca5d7de558a26c183987e6e68253df8694e6..3701f41dca0b1c192d6ef54cf3a54926ce3e16db 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.138 2002/12/27 20:06:19 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.139 2003/01/09 20:50:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -367,6 +367,8 @@ transformExpr(ParseState *pstate, Node *expr)
 					 */
 					sublink->lefthand = NIL;
 					sublink->oper = NIL;
+					sublink->operIsEquals = FALSE;
+					sublink->useOr = FALSE;
 				}
 				else if (sublink->subLinkType == EXPR_SUBLINK)
 				{
@@ -391,27 +393,60 @@ transformExpr(ParseState *pstate, Node *expr)
 					 */
 					sublink->lefthand = NIL;
 					sublink->oper = NIL;
+					sublink->operIsEquals = FALSE;
+					sublink->useOr = FALSE;
 				}
 				else
 				{
 					/* ALL, ANY, or MULTIEXPR: generate operator list */
 					List	   *left_list = sublink->lefthand;
 					List	   *right_list = qtree->targetList;
+					int			row_length = length(left_list);
+					bool		needNot = false;
 					List	   *op;
 					char	   *opname;
 					List	   *elist;
 
+					/* transform lefthand expressions */
 					foreach(elist, left_list)
 						lfirst(elist) = transformExpr(pstate, lfirst(elist));
 
+					/* get the combining-operator name */
 					Assert(IsA(sublink->oper, A_Expr));
 					op = ((A_Expr *) sublink->oper)->name;
 					opname = strVal(llast(op));
 					sublink->oper = NIL;
 
+					/*
+					 * If the expression is "<> ALL" (with unqualified opname)
+					 * then convert it to "NOT IN".  This is a hack to improve
+					 * efficiency of expressions output by pre-7.4 Postgres.
+					 */
+					if (sublink->subLinkType == ALL_SUBLINK &&
+						length(op) == 1 && strcmp(opname, "<>") == 0)
+					{
+						sublink->subLinkType = ANY_SUBLINK;
+						opname = pstrdup("=");
+						op = makeList1(makeString(opname));
+						needNot = true;
+					}
+
+					/* Set operIsEquals if op is unqualified "=" */
+					if (length(op) == 1 && strcmp(opname, "=") == 0)
+						sublink->operIsEquals = TRUE;
+					else
+						sublink->operIsEquals = FALSE;
+
+					/* Set useOr if op is "<>" (possibly qualified) */
+					if (strcmp(opname, "<>") == 0)
+						sublink->useOr = TRUE;
+					else
+						sublink->useOr = FALSE;
+
 					/* Combining operators other than =/<> is dubious... */
-					if (length(left_list) != 1 &&
-					strcmp(opname, "=") != 0 && strcmp(opname, "<>") != 0)
+					if (row_length != 1 &&
+						strcmp(opname, "=") != 0 &&
+						strcmp(opname, "<>") != 0)
 						elog(ERROR, "Row comparison cannot use operator %s",
 							 opname);
 
@@ -474,6 +509,13 @@ transformExpr(ParseState *pstate, Node *expr)
 					}
 					if (left_list != NIL)
 						elog(ERROR, "Subselect has too few fields");
+
+					if (needNot)
+					{
+						expr = coerce_to_boolean(expr, "NOT");
+						expr = (Node *) makeBoolExpr(NOT_EXPR,
+													 makeList1(expr));
+					}
 				}
 				result = (Node *) expr;
 				break;
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 0275d8424acc86ce8d75b5f5e46a74847eb64d08..a8679463670859bee1e1f8a2a6efed82c6a294e8 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
  *				back to source text
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.130 2003/01/08 22:54:06 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.131 2003/01/09 20:50:52 tgl Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -2660,8 +2660,16 @@ get_sublink_expr(SubLink *sublink, deparse_context *context)
 			break;
 
 		case ANY_SUBLINK:
-			oper = (OpExpr *) lfirst(sublink->oper);
-			appendStringInfo(buf, "%s ANY ", get_opname(oper->opno));
+			if (sublink->operIsEquals)
+			{
+				/* Represent it as IN */
+				appendStringInfo(buf, "IN ");
+			}
+			else
+			{
+				oper = (OpExpr *) lfirst(sublink->oper);
+				appendStringInfo(buf, "%s ANY ", get_opname(oper->opno));
+			}
 			break;
 
 		case ALL_SUBLINK:
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 710b5c71ac888ab3c4fb755981189a6bb213185f..9c3e5906adeb9d69788123327e43cc9c71f2b2bd 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.170 2002/12/12 21:02:25 momjian Exp $
+ * $Id: catversion.h,v 1.171 2003/01/09 20:50:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200212121
+#define CATALOG_VERSION_NO	200301091
 
 #endif
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 285a0008fdc31d90c94414f5014b2ec1141d5cd3..d9ea05994dd326a46703cf02676cfd0cafdef1cb 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: primnodes.h,v 1.75 2002/12/14 00:17:59 tgl Exp $
+ * $Id: primnodes.h,v 1.76 2003/01/09 20:50:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -374,7 +374,7 @@ typedef struct BoolExpr
  * MULTIEXPR and EXPR require the subselect to deliver only one row.
  * ALL, ANY, and MULTIEXPR require the combining operators to deliver boolean
  * results.  These are reduced to one result per row using OR or AND semantics
- * depending on the "useor" flag.  ALL and ANY combine the per-row results
+ * depending on the "useOr" flag.  ALL and ANY combine the per-row results
  * using AND and OR semantics respectively.
  *
  * SubLink is classed as an Expr node, but it is not actually executable;
@@ -395,7 +395,11 @@ typedef struct BoolExpr
  * rewriter.
  *
  * In EXISTS and EXPR SubLinks, both lefthand and oper are unused and are
- * always NIL.	useor is not significant either for these sublink types.
+ * always NIL.	useOr is not significant either for these sublink types.
+ *
+ * The operIsEquals field is TRUE when the combining operator was written as
+ * "=" --- if the subLinkType is ANY_SUBLINK, this means the operation is
+ * equivalent to "IN".  This case allows special optimizations to be used.
  * ----------------
  */
 typedef enum SubLinkType
@@ -408,7 +412,8 @@ typedef struct SubLink
 {
 	Expr		xpr;
 	SubLinkType subLinkType;	/* EXISTS, ALL, ANY, MULTIEXPR, EXPR */
-	bool		useor;			/* TRUE to combine column results with
+	bool		operIsEquals;	/* TRUE if combining operator is "=" */
+	bool		useOr;			/* TRUE to combine column results with
 								 * "OR" not "AND" */
 	List	   *lefthand;		/* list of outer-query expressions on the
 								 * left */
@@ -446,7 +451,7 @@ typedef struct SubPlan
 	Expr		xpr;
 	/* Fields copied from original SubLink: */
 	SubLinkType subLinkType;	/* EXISTS, ALL, ANY, MULTIEXPR, EXPR */
-	bool		useor;			/* TRUE to combine column results with
+	bool		useOr;			/* TRUE to combine column results with
 								 * "OR" not "AND" */
 	List	   *oper;			/* list of executable expressions for
 								 * combining operators (with arguments) */