*** ./src/backend/optimizer/plan/initsplan.c.orig	Tue Sep 21 16:38:11 1999
--- ./src/backend/optimizer/plan/initsplan.c	Tue Sep 21 16:47:31 1999
***************
*** 134,140 ****
--- 134,143 ----
  	List	   *clause;
  
  	foreach(clause, clauses)
+ 	{
+ 		clause = (List *) eval_const_expressions((Node *) clause, NULL);
  		add_restrict_and_join_to_rel(root, (Node *) lfirst(clause));
+ 	}
  }
  
  /*
*** ./src/backend/optimizer/util/clauses.c.orig	Tue Sep 21 16:38:12 1999
--- ./src/backend/optimizer/util/clauses.c	Tue Sep 21 16:47:31 1999
***************
*** 765,770 ****
--- 765,898 ----
  	lsecond(clause->args) = temp;
  }
  
+ /*
+    A mutator that destructively modifies the input tree by evaluating
+    function and operator expressions with constant arguments.  All
+    other nodes are passed direcly to the output without evaluation.
+    The function only traverses a connected tree of expression nodes
+    that are lists, operators or functions.
+ */
+ 
+ Node *
+ eval_const_expressions(Node *node, void *context)
+ {
+ 	if (node == NULL)
+ 		return NULL;
+ 
+ 	/*
+ 	 * We only descend Expr nodes that are not SUB_PLANS, and List nodes.
+ 	 * All other nodes are passed straight to the output tree.
+ 	 */
+ 	switch (nodeTag(node))
+ 	{
+ 		case T_List:
+ 			return (Node *) expression_tree_mutator(node, eval_const_expressions,
+ 													context);
+ 
+ 		case T_Const:
+ 			return node;
+ 
+ 		case T_Expr:
+ 			{
+ 				Expr	   *expr = (Expr *) node;
+ 				bool		args_are_const = TRUE;
+ 				bool		const_is_null = FALSE;
+ 				bool		isDone = FALSE;
+ 				Datum		const_val;
+ 				Const	   *constant;
+ 
+ 				switch (expr->opType)
+ 				{
+ 					case SUBPLAN_EXPR:	/* Pass subplan nodes through. */
+ 						if (context)
+ 							*((bool *) context) = FALSE;
+ 						return node;
+ 					default:	/* Descend on all other expression nodes. */
+ 						node = expression_tree_mutator(node, eval_const_expressions,
+ 													   &args_are_const);
+ 				}
+ 
+ 				if (args_are_const == FALSE)
+ 				{
+ 					if (context)
+ 						*((bool *) context) = false;
+ 					return node;
+ 				}
+ 
+ 				/* The node is a constant expression */
+ 
+ 				/*
+ 				 * Check that we have a reference to the object for the
+ 				 * expression
+ 				 */
+ 				if (expr->opType == OP_EXPR)
+ 				{				/* Check that the operator function is
+ 								 * valid */
+ 					Oper	   *opr = (Oper *) expr->oper;
+ 
+ 					if (!OidIsValid(opr->opid))
+ 					{
+ 						opr->opid = get_opcode(opr->opno);
+ 
+ 						if (!OidIsValid(opr->opid))
+ 							elog(ERROR,
+ 								 "eval_cons_exressions: %s %u",
+ 								 "Cache lookup failed for operator", opr->opno);
+ 					}
+ 				}
+ 
+ 				/* Evaluate the expression */
+ 
+ 				/*
+ 				 * Note it is O.K. to set the econtext argument to null,
+ 				 * because none of the routines called by the next
+ 				 * statement use econtext when the arguments to the
+ 				 * expression are all constants.
+ 				 */
+ 
+ 				const_val = ExecEvalExpr(node, NULL, &const_is_null, &isDone);
+ 				Assert(isDone);
+ 
+ 				switch (expr->opType)
+ 				{
+ 					case FUNC_EXPR:
+ 						{
+ 							Func	   *func = (Func *) expr->oper;
+ 
+ 							constant = makeConst(func->functype, func->funcsize,
+ 												 const_val, const_is_null,
+ 											 func->func_fcache->typbyval,
+ 												 FALSE, FALSE);
+ 							break;
+ 						}
+ 					case OP_EXPR:
+ 						{
+ 							Oper	   *oper = (Oper *) expr->oper;
+ 
+ 							constant = makeConst(oper->opresulttype, oper->opsize,
+ 												 const_val, const_is_null,
+ 											   oper->op_fcache->typbyval,
+ 												 FALSE, FALSE);
+ 							break;
+ 						}
+ 					default:	/* Must be a Boolean expression. */
+ 						constant = makeConst(expr->typeOid, sizeof(Datum),
+ 											 const_val, const_is_null,
+ 											 TRUE, FALSE, FALSE);
+ 
+ 				}
+ 
+ 				return (Node *) constant;
+ 			}					/* End of case T_Expr: */
+ 
+ 		default:				/* All other nodes drop through. */
+ 	}
+ 
+ 	/* Found a node that can't be in a constant expression tree */
+ 	if (context)
+ 		*((bool *) context) = FALSE;
+ 	return node;
+ }
  
  /*
   * Standard expression-tree walking support
*** ./src/include/optimizer/clauses.h.orig	Tue Sep 21 16:38:12 1999
--- ./src/include/optimizer/clauses.h	Tue Sep 21 16:47:32 1999
***************
*** 52,57 ****
--- 52,59 ----
  			  AttrNumber *attno1, int *relid2, AttrNumber *attno2);
  extern void CommuteClause(Expr *clause);
  
+ extern Node *eval_const_expressions(Node *node, void *context);
+ 
  extern bool expression_tree_walker(Node *node, bool (*walker) (),
  											   void *context);
  extern Node *expression_tree_mutator(Node *node, Node *(*mutator) (),