diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 39f13e5a3e5cf107775fa8cecd123ef1f995736a..242973f20f656eee0cf19e04a64a8b5023a0d644 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.182 2002/11/25 21:29:34 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.183 2002/11/26 03:01:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -749,7 +749,6 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
 	FmgrInfo   *in_functions;
 	Oid		   *elements;
 	Node	  **constraintexprs;
-	Const	  **constraintconsts;
 	bool		hasConstraints = false;
 	int			i;
 	List	   *cur;
@@ -805,7 +804,6 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
 	defmap = (int *) palloc(num_phys_attrs * sizeof(int));
 	defexprs = (Node **) palloc(num_phys_attrs * sizeof(Node *));
 	constraintexprs = (Node **) palloc0(num_phys_attrs * sizeof(Node *));
-	constraintconsts = (Const **) palloc(num_phys_attrs * sizeof(Const *));
 
 	for (i = 0; i < num_phys_attrs; i++)
 	{
@@ -840,7 +838,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
 		/* If it's a domain type, get info on domain constraints */
 		if (get_typtype(attr[i]->atttypid) == 'd')
 		{
-			Const	   *con;
+			Param	   *prm;
 			Node	   *node;
 
 			/*
@@ -848,28 +846,21 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
 			 * an expression that checks the constraints.  (At present,
 			 * the expression might contain a length-coercion-function call
 			 * and/or ConstraintTest nodes.)  The bottom of the expression
-			 * is a Const node that we fill in with the actual datum during
+			 * is a Param node so that we can fill in the actual datum during
 			 * the data input loop.
-			 *
-			 * XXX to prevent premature constant folding in parse_coerce,
-			 * pass in a NULL constant to start with.  See the comments in
-			 * coerce_type; this should be changed someday to use some sort
-			 * of Param node instead of a Const.
 			 */
-			con = makeConst(attr[i]->atttypid,
-							attr[i]->attlen,
-							(Datum) 0,
-							true,		 /* is null */
-							attr[i]->attbyval);
+			prm = makeNode(Param);
+			prm->paramkind = PARAM_EXEC;
+			prm->paramid = 0;
+			prm->paramtype = attr[i]->atttypid;
 
-			node = coerce_type_constraints((Node *) con, attr[i]->atttypid,
+			node = coerce_type_constraints((Node *) prm, attr[i]->atttypid,
 										   COERCE_IMPLICIT_CAST);
 
 			/* check whether any constraints actually found */
-			if (node != (Node *) con)
+			if (node != (Node *) prm)
 			{
 				constraintexprs[i] = node;
-				constraintconsts[i] = con;
 				hasConstraints = true;
 			}
 		}
@@ -931,6 +922,11 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
 
 	econtext = GetPerTupleExprContext(estate);
 
+	/* Make room for a PARAM_EXEC value for domain constraint checks */
+	if (hasConstraints)
+		econtext->ecxt_param_exec_vals = (ParamExecData *)
+			palloc0(sizeof(ParamExecData));
+
 	while (!done)
 	{
 		bool		skip_tuple;
@@ -1153,19 +1149,19 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
 		 */
 		if (hasConstraints)
 		{
+			ParamExecData *prmdata = &econtext->ecxt_param_exec_vals[0];
+
 			for (i = 0; i < num_phys_attrs; i++)
 			{
 				Node	   *node = constraintexprs[i];
-				Const	   *con;
 				bool		isnull;
 
 				if (node == NULL)
 					continue;	/* no constraint for this attr */
 
-				/* Insert current row's value into the Const node */
-				con = constraintconsts[i];
-				con->constvalue = values[i];
-				con->constisnull = (nulls[i] == 'n');
+				/* Insert current row's value into the Param value */
+				prmdata->value = values[i];
+				prmdata->isnull = (nulls[i] == 'n');
 
 				/*
 				 * Execute the constraint expression.  Allow the expression
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 0c7b3557cff89a9af577217b7e71453a0462b2d3..73ff6370fbcd99a935124ad07540d392351e0605 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.33 2002/06/20 20:29:28 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.34 2002/11/26 03:01:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -150,37 +150,44 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
 		foreach(lst, sublink->oper)
 		{
 			Expr	   *expr = (Expr *) lfirst(lst);
-			Const	   *con = lsecond(expr->args);
+			Param	   *prm = lsecond(expr->args);
+			ParamExecData *prmdata;
 			Datum		expresult;
 			bool		expnull;
 
 			/*
 			 * The righthand side of the expression should be either a
-			 * Const or a function call or RelabelType node taking a Const
+			 * Param or a function call or RelabelType node taking a Param
 			 * as arg (these nodes represent run-time type coercions
 			 * inserted by the parser to get to the input type needed by
-			 * the operator). Find the Const node and insert the actual
-			 * righthand-side value into it.
+			 * the operator). Find the Param node and insert the actual
+			 * righthand-side value into the param's econtext slot.
+			 *
+			 * XXX possible improvement: could make a list of the ParamIDs
+			 * at startup time, instead of repeating this check at each row.
 			 */
-			if (!IsA(con, Const))
+			if (!IsA(prm, Param))
 			{
-				switch (con->type)
+				switch (nodeTag(prm))
 				{
 					case T_Expr:
-						con = lfirst(((Expr *) con)->args);
+						prm = lfirst(((Expr *) prm)->args);
 						break;
 					case T_RelabelType:
-						con = (Const *) (((RelabelType *) con)->arg);
+						prm = (Param *) (((RelabelType *) prm)->arg);
 						break;
 					default:
 						/* will fail below */
 						break;
 				}
-				if (!IsA(con, Const))
+				if (!IsA(prm, Param))
 					elog(ERROR, "ExecSubPlan: failed to find placeholder for subplan result");
 			}
-			con->constvalue = heap_getattr(tup, col, tdesc,
-										   &(con->constisnull));
+			Assert(prm->paramkind == PARAM_EXEC);
+			prmdata = &(econtext->ecxt_param_exec_vals[prm->paramid]);
+			Assert(prmdata->execPlan == NULL);
+			prmdata->value = heap_getattr(tup, col, tdesc,
+										  &(prmdata->isnull));
 
 			/*
 			 * Now we can eval the combining operator for this column.
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 9a5141ea6b94891b55eda99014626783568652a0..2c1081f2677ac7ddefaf9c24cbc63316c708dc76 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.130 2002/11/21 00:42:19 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.131 2002/11/26 03:01:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -720,8 +720,6 @@ preprocess_expression(Query *parse, Node *expr, int kind)
 	 *
 	 * Note that at this point quals have not yet been converted to
 	 * implicit-AND form, so we can apply eval_const_expressions directly.
-	 * Also note that we need to do this before SS_process_sublinks,
-	 * because that routine inserts bogus "Const" nodes.
 	 */
 	expr = eval_const_expressions(expr);
 
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 1dcebba2e773282b9de52722f6ec63b8e9c28f57..5b171fb819a20babcc31e48250bdf0364a59a686 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.55 2002/09/04 20:31:21 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.56 2002/11/26 03:01:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,24 +44,32 @@ int			PlannerPlanId = 0;	/* to assign unique ID to subquery plans */
  * and update the list elements when we enter or exit a subplan
  * recursion level.  But we must pay attention not to confuse this
  * meaning with the normal meaning of varlevelsup.
+ *
+ * We also need to create Param slots that don't correspond to any outer Var.
+ * For these, we set varno = 0 and varlevelsup = 0, so that they can't
+ * accidentally match an outer Var.
  *--------------------
  */
 
 
+static void convert_sublink_opers(SubLink *slink, List *targetlist,
+								  List **setParams);
+
+
 /*
  * Create a new entry in the PlannerParamVar list, and return its index.
  *
- * var contains the data to be copied, except for varlevelsup which
- * is set from the absolute level value given by varlevel.
+ * var contains the data to use, except for varlevelsup which
+ * is set from the absolute level value given by varlevel.  NOTE that
+ * the passed var is scribbled on and placed directly into the list!
+ * Generally, caller should have just created or copied it.
  */
 static int
 new_param(Var *var, Index varlevel)
 {
-	Var		   *paramVar = (Var *) copyObject(var);
+	var->varlevelsup = varlevel;
 
-	paramVar->varlevelsup = varlevel;
-
-	PlannerParamVar = lappend(PlannerParamVar, paramVar);
+	PlannerParamVar = lappend(PlannerParamVar, var);
 
 	return length(PlannerParamVar) - 1;
 }
@@ -107,7 +115,7 @@ replace_var(Var *var)
 	if (!ppv)
 	{
 		/* Nope, so make a new one */
-		i = new_param(var, varlevel);
+		i = new_param((Var *) copyObject(var), varlevel);
 	}
 
 	retval = makeNode(Param);
@@ -118,6 +126,22 @@ replace_var(Var *var)
 	return retval;
 }
 
+/*
+ * Generate a new Param node that will not conflict with any other.
+ */
+static Param *
+generate_new_param(Oid paramtype, int32 paramtypmod)
+{
+	Var		   *var = makeVar(0, 0, paramtype, paramtypmod, 0);
+	Param	   *retval = makeNode(Param);
+
+	retval->paramkind = PARAM_EXEC;
+	retval->paramid = (AttrNumber) new_param(var, 0);
+	retval->paramtype = paramtype;
+
+	return retval;
+}
+
 /*
  * Convert a bare SubLink (as created by the parser) into a SubPlan.
  */
@@ -216,13 +240,9 @@ make_subplan(SubLink *slink)
 	 */
 	if (node->parParam == NIL && slink->subLinkType == EXISTS_SUBLINK)
 	{
-		Var		   *var = makeVar(0, 0, BOOLOID, -1, 0);
-		Param	   *prm = makeNode(Param);
+		Param	   *prm;
 
-		prm->paramkind = PARAM_EXEC;
-		prm->paramid = (AttrNumber) new_param(var, PlannerQueryLevel);
-		prm->paramtype = var->vartype;
-		pfree(var);				/* var is only needed for new_param */
+		prm = generate_new_param(BOOLOID, -1);
 		node->setParam = lappendi(node->setParam, prm->paramid);
 		PlannerInitPlan = lappend(PlannerInitPlan, node);
 		result = (Node *) prm;
@@ -230,89 +250,27 @@ make_subplan(SubLink *slink)
 	else if (node->parParam == NIL && slink->subLinkType == EXPR_SUBLINK)
 	{
 		TargetEntry *te = lfirst(plan->targetlist);
+		Param	   *prm;
 
-		/* need a var node just to pass to new_param()... */
-		Var		   *var = makeVar(0, 0, te->resdom->restype,
-								  te->resdom->restypmod, 0);
-		Param	   *prm = makeNode(Param);
-
-		prm->paramkind = PARAM_EXEC;
-		prm->paramid = (AttrNumber) new_param(var, PlannerQueryLevel);
-		prm->paramtype = var->vartype;
-		pfree(var);				/* var is only needed for new_param */
+		prm = generate_new_param(te->resdom->restype, te->resdom->restypmod);
 		node->setParam = lappendi(node->setParam, prm->paramid);
 		PlannerInitPlan = lappend(PlannerInitPlan, node);
 		result = (Node *) prm;
 	}
 	else if (node->parParam == NIL && slink->subLinkType == MULTIEXPR_SUBLINK)
 	{
-		List	   *newoper = NIL;
-		int			i = 0;
-
-		/*
-		 * Convert oper list of Opers into a list of Exprs, using lefthand
-		 * arguments and Params representing inside results.
-		 */
-		foreach(lst, slink->oper)
-		{
-			Oper	   *oper = (Oper *) lfirst(lst);
-			Node	   *lefthand = nth(i, slink->lefthand);
-			TargetEntry *te = nth(i, plan->targetlist);
-
-			/* need a var node just to pass to new_param()... */
-			Var		   *var = makeVar(0, 0, te->resdom->restype,
-									  te->resdom->restypmod, 0);
-			Param	   *prm = makeNode(Param);
-			Operator	tup;
-			Form_pg_operator opform;
-			Node	   *left,
-					   *right;
-
-			prm->paramkind = PARAM_EXEC;
-			prm->paramid = (AttrNumber) new_param(var, PlannerQueryLevel);
-			prm->paramtype = var->vartype;
-			pfree(var);			/* var is only needed for new_param */
-
-			Assert(IsA(oper, Oper));
-			tup = SearchSysCache(OPEROID,
-								 ObjectIdGetDatum(oper->opno),
-								 0, 0, 0);
-			if (!HeapTupleIsValid(tup))
-				elog(ERROR, "cache lookup failed for operator %u", oper->opno);
-			opform = (Form_pg_operator) GETSTRUCT(tup);
-
-			/*
-			 * Note: we use make_operand in case runtime type conversion
-			 * function calls must be inserted for this operator!
-			 */
-			left = make_operand(lefthand,
-								exprType(lefthand), opform->oprleft);
-			right = make_operand((Node *) prm,
-								 prm->paramtype, opform->oprright);
-			ReleaseSysCache(tup);
-
-			newoper = lappend(newoper,
-							  make_opclause(oper,
-											(Var *) left,
-											(Var *) right));
-			node->setParam = lappendi(node->setParam, prm->paramid);
-			i++;
-		}
-		slink->oper = newoper;
-		slink->lefthand = NIL;
+		convert_sublink_opers(slink, plan->targetlist, &node->setParam);
 		PlannerInitPlan = lappend(PlannerInitPlan, node);
-		if (i > 1)
-			result = (Node *) ((slink->useor) ? make_orclause(newoper) :
-							   make_andclause(newoper));
+		if (length(slink->oper) > 1)
+			result = (Node *) ((slink->useor) ? make_orclause(slink->oper) :
+							   make_andclause(slink->oper));
 		else
-			result = (Node *) lfirst(newoper);
+			result = (Node *) lfirst(slink->oper);
 	}
 	else
 	{
 		Expr	   *expr = makeNode(Expr);
 		List	   *args = NIL;
-		List	   *newoper = NIL;
-		int			i = 0;
 
 		/*
 		 * We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types
@@ -379,6 +337,9 @@ make_subplan(SubLink *slink)
 			}
 		}
 
+		/* Fix the SubLink's oper list */
+		convert_sublink_opers(slink, plan->targetlist, NULL);
+
 		/*
 		 * Make expression of SUBPLAN type
 		 */
@@ -405,53 +366,82 @@ make_subplan(SubLink *slink)
 		}
 		expr->args = args;
 
+		result = (Node *) expr;
+	}
+
+	return result;
+}
+
+/*
+ * convert_sublink_opers: convert a SubLink's oper list from the
+ * parser/rewriter format into the executor's format.
+ *
+ * The oper list is initially just a list of Oper nodes.  We replace it
+ * with a list of actually executable expressions, in which the specified
+ * operators are applied to corresponding elements of the lefthand list
+ * and Params representing the results of the subplan.  lefthand is then
+ * set to NIL.
+ *
+ * If setParams is not NULL, the paramids of the Params created are added
+ * to the *setParams list.
+ */
+static void
+convert_sublink_opers(SubLink *slink, List *targetlist,
+					  List **setParams)
+{
+	List	   *newoper = NIL;
+	List	   *leftlist = slink->lefthand;
+	List	   *lst;
+
+	foreach(lst, slink->oper)
+	{
+		Oper	   *oper = (Oper *) lfirst(lst);
+		Node	   *lefthand = lfirst(leftlist);
+		TargetEntry *te = lfirst(targetlist);
+		Param	   *prm;
+		Operator	tup;
+		Form_pg_operator opform;
+		Node	   *left,
+				   *right;
+
+		/* Make the Param node representing the subplan's result */
+		prm = generate_new_param(te->resdom->restype,
+								 te->resdom->restypmod);
+
+		/* Record its ID if needed */
+		if (setParams)
+			*setParams = lappendi(*setParams, prm->paramid);
+
+		/* Look up the operator to check its declared input types */
+		Assert(IsA(oper, Oper));
+		tup = SearchSysCache(OPEROID,
+							 ObjectIdGetDatum(oper->opno),
+							 0, 0, 0);
+		if (!HeapTupleIsValid(tup))
+			elog(ERROR, "cache lookup failed for operator %u", oper->opno);
+		opform = (Form_pg_operator) GETSTRUCT(tup);
+
 		/*
-		 * Convert oper list of Opers into a list of Exprs, using lefthand
-		 * arguments and Consts representing inside results.
+		 * Make the expression node.
+		 *
+		 * Note: we use make_operand in case runtime type conversion
+		 * function calls must be inserted for this operator!
 		 */
-		foreach(lst, slink->oper)
-		{
-			Oper	   *oper = (Oper *) lfirst(lst);
-			Node	   *lefthand = nth(i, slink->lefthand);
-			TargetEntry *te = nth(i, plan->targetlist);
-			Const	   *con;
-			Operator	tup;
-			Form_pg_operator opform;
-			Node	   *left,
-					   *right;
-
-			con = makeNullConst(te->resdom->restype);
-
-			Assert(IsA(oper, Oper));
-			tup = SearchSysCache(OPEROID,
-								 ObjectIdGetDatum(oper->opno),
-								 0, 0, 0);
-			if (!HeapTupleIsValid(tup))
-				elog(ERROR, "cache lookup failed for operator %u", oper->opno);
-			opform = (Form_pg_operator) GETSTRUCT(tup);
+		left = make_operand(lefthand, exprType(lefthand), opform->oprleft);
+		right = make_operand((Node *) prm, prm->paramtype, opform->oprright);
+		newoper = lappend(newoper,
+						  make_opclause(oper,
+										(Var *) left,
+										(Var *) right));
 
-			/*
-			 * Note: we use make_operand in case runtime type conversion
-			 * function calls must be inserted for this operator!
-			 */
-			left = make_operand(lefthand,
-								exprType(lefthand), opform->oprleft);
-			right = make_operand((Node *) con,
-								 con->consttype, opform->oprright);
-			ReleaseSysCache(tup);
-
-			newoper = lappend(newoper,
-							  make_opclause(oper,
-											(Var *) left,
-											(Var *) right));
-			i++;
-		}
-		slink->oper = newoper;
-		slink->lefthand = NIL;
-		result = (Node *) expr;
+		ReleaseSysCache(tup);
+
+		leftlist = lnext(leftlist);
+		targetlist = lnext(targetlist);
 	}
 
-	return result;
+	slink->oper = newoper;
+	slink->lefthand = NIL;
 }
 
 /*
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 2bc1c2afbec244d0c1c975bfb6c2d9661ddd4ab7..8ba8483a9573d536357faaef3f24379e18293551 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.112 2002/11/25 21:29:40 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.113 2002/11/26 03:01:58 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -1135,14 +1135,6 @@ CommuteClause(Expr *clause)
  *
  * We assume that the tree has already been type-checked and contains
  * only operators and functions that are reasonable to try to execute.
- *
- * This routine should be invoked before converting sublinks to subplans
- * (subselect.c's SS_process_sublinks()).  The converted form contains
- * bogus "Const" nodes that are actually placeholders where the executor
- * will insert values from the inner plan, and obviously we mustn't try
- * to reduce the expression as though these were really constants.
- * As a safeguard, if we happen to find an already-converted SubPlan node,
- * we will return it unchanged rather than recursing into it.
  *--------------------
  */
 Node *
@@ -1411,11 +1403,13 @@ eval_const_expressions_mutator(Node *node, void *context)
 			case SUBPLAN_EXPR:
 
 				/*
-				 * Safety measure per notes at head of this routine:
-				 * return a SubPlan unchanged.	Too late to do anything
+				 * Return a SubPlan unchanged --- too late to do anything
 				 * with it.  The arglist simplification above was wasted
 				 * work (the list probably only contains Var nodes
 				 * anyway).
+				 *
+				 * XXX should we elog() here instead?  Probably this routine
+				 * should never be invoked after SubPlan creation.
 				 */
 				return (Node *) expr;
 			default:
@@ -1629,7 +1623,6 @@ simplify_op_or_func(Expr *expr, List *args)
 	 *
 	 * Note we take the result type from the Oper or Func node, not the
 	 * pg_proc tuple; probably necessary for binary-compatibility cases.
-	 *
 	 */
 	if (expr->opType == OP_EXPR)
 	{
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index e65590862862964f36590103a0e2716e6af9bb38..2809a9a17f15a98814c8158af53bd12589b5a76c 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.87 2002/11/25 21:29:41 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.88 2002/11/26 03:01:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -241,14 +241,8 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId,
 			 *
 			 * Note that no folding will occur if the conversion function is
 			 * not marked 'immutable'.
-			 *
-			 * HACK: if constant is NULL, don't fold it here.  This is needed
-			 * by make_subplan(), which calls this routine on placeholder
-			 * Const nodes that mustn't be collapsed.  (It'd be a lot
-			 * cleaner to make a separate node type for that purpose...)
 			 */
-			if (IsA(node, Const) &&
-				!((Const *) node)->constisnull)
+			if (IsA(node, Const))
 				result = eval_const_expressions(result);
 		}
 		else
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 9a4a9c8bc91e33fb226d0a883db5fef03782bd32..fd2cd4f34b3427da83ff319678d523d1e2776088 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.130 2002/11/15 02:50:09 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.131 2002/11/26 03:01:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -122,7 +122,6 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
 				param = makeNode(Param);
 				param->paramkind = PARAM_NUM;
 				param->paramid = (AttrNumber) paramno;
-				param->paramname = "<unnamed>";
 				param->paramtype = paramtyp;
 				result = (Node *) param;
 				/* handle qualification, if any */
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 01aac333b5e49fb3b07516834ec3431a740bca30..c5a0f0d75d853fa8d70399c8c317acfc090e4535 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.126 2002/11/25 21:29:41 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.127 2002/11/26 03:01:58 tgl Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -1921,7 +1921,6 @@ get_rule_expr(Node *node, deparse_context *context,
 	 * same expression tree.
 	 *
 	 * There might be some work left here to support additional node types.
-	 * Can we ever see Param nodes here?
 	 */
 	switch (nodeTag(node))
 	{
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index f0f37c3d9d33dd5dda9d8d7169641027dbf3db8f..089f7362a6b42a3e6163d5d630ec4f54812bcea0 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.69 2002/11/25 21:29:42 tgl Exp $
+ * $Id: primnodes.h,v 1.70 2002/11/26 03:01:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -357,7 +357,7 @@ typedef struct Aggref
  * 3. Finally, the planner converts the oper list to a list of normal Expr
  *	  nodes representing the application of the operator(s) to the lefthand
  *	  expressions and values from the inner targetlist.  The inner
- *	  targetlist items are represented by placeholder Param or Const nodes.
+ *	  targetlist items are represented by placeholder Param nodes.
  *	  The lefthand field is set to NIL, since its expressions are now in
  *	  the Expr list.  This representation is passed to the executor.
  *