diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index 6360f004b75dff47cda5c546e47acb0158826249..ac4a4d0d2042ea0c9c68eb2c33494f8c39ff5905 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.22 1998/06/15 19:28:17 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.23 1998/07/19 05:49:12 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -222,6 +222,9 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
 	OffsetVarNodes((Node *) viewParse->targetList, 2);
 	OffsetVarNodes(viewParse->qual, 2);
 
+	OffsetVarNodes(viewParse->havingQual, 2);
+	
+
 	/*
 	 * find the old range table...
 	 */
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 58c837e8e9c85f9937e3864dac40ea0451076b0b..28f50bdd4f435accd560537403ff0222176464a0 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -109,22 +109,24 @@ ExecAgg(Agg *node)
 	bool		isNull = FALSE,
 				isNull1 = FALSE,
 				isNull2 = FALSE;
-
-
-	do { 
-
+	bool  qual_result;
+	
 
 	/* ---------------------
 	 *	get state info from node
 	 * ---------------------
 	 */
 
+	/* We loop retrieving groups until we find one matching node->plan.qual */
+	do { 
+
 	aggstate = node->aggstate;
 	if (aggstate->agg_done)
 		return NULL;
 
 	estate = node->plan.state;
 	econtext = aggstate->csstate.cstate.cs_ExprContext;
+
 	nagg = length(node->aggs);
 
 	aggregates = (Aggreg **) palloc(sizeof(Aggreg *) * nagg);
@@ -235,8 +237,7 @@ ExecAgg(Agg *node)
 			}
 		}
 	}
-	  
-
+	  	  
 	/* ----------------
 	 *	 for each tuple from the the outer plan, apply all the aggregates
 	 * ----------------
@@ -474,11 +475,6 @@ ExecAgg(Agg *node)
 	 *	slot and return it.
 	 * ----------------
 	 */
-
-	}
-	while((ExecQual(fix_opids(node->plan.qual),econtext)!=true) && 
-	      (node->plan.qual!=NULL));
-
 	 
 	ExecStoreTuple(oneTuple,
 				   aggstate->csstate.css_ScanTupleSlot,
@@ -488,8 +484,13 @@ ExecAgg(Agg *node)
 
 	resultSlot = ExecProject(projInfo, &isDone);
 
+	/* As long as the retrieved group does not match the qualifications it is ignored and
+	 * the next group is fetched */	
+	qual_result=ExecQual(fix_opids(node->plan.qual),econtext);
 	if (oneTuple)
-		pfree(oneTuple);
+	  pfree(oneTuple);
+	} 
+	while((node->plan.qual!=NULL) && (qual_result!=true));
 
 	return resultSlot;
 }
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index d3a1bdb62ea6c60e13e32fb2aa5a0ee855586c52..5483c864d35b99193183161c4aef426858cafe35 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.16 1998/06/15 19:28:22 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.17 1998/07/19 05:49:13 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -365,7 +365,9 @@ CleanUpSort(Plan *plan)
 	{
 		Sort	   *sort = (Sort *) plan;
 
-		psort_end(sort);
+		/* This may need to be fixed or moved somewhere else, bjm */
+		/* psort_end(sort); */
+
 	}
 }
 
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index c88d201501cde45ebf881729e350e10ac8cf18eb..51a93517c17cdd4ce9fbdfa6072be4ae8a048a7a 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.27 1998/04/15 15:29:41 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.28 1998/07/19 05:49:14 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -95,6 +95,11 @@ Plan *
 union_planner(Query *parse)
 {
 	List	   *tlist = parse->targetList;
+
+	/* copy the original tlist, we will need the original one 
+	 * for the AGG node later on */
+	List    *new_tlist = new_unsorted_tlist(tlist);	
+	
 	List	   *rangetable = parse->rtable;
 
 	Plan	   *result_plan = (Plan *) NULL;
@@ -104,12 +109,12 @@ union_planner(Query *parse)
 
 	if (parse->unionClause)
 	{
-		result_plan = (Plan *) plan_union_queries(parse);
-		/* XXX do we need to do this? bjm 12/19/97 */
-		tlist = preprocess_targetlist(tlist,
-									  parse->commandType,
-									  parse->resultRelation,
-									  parse->rtable);
+	  result_plan = (Plan *) plan_union_queries(parse);
+	  /* XXX do we need to do this? bjm 12/19/97 */	  	  
+	  tlist = preprocess_targetlist(tlist,
+					parse->commandType,
+					parse->resultRelation,
+					parse->rtable);
 	}
 	else if ((rt_index =
 			  first_inherit_rt_entry(rangetable)) != -1)
@@ -117,33 +122,64 @@ union_planner(Query *parse)
 		result_plan = (Plan *) plan_inherit_queries(parse, rt_index);
 		/* XXX do we need to do this? bjm 12/19/97 */
 		tlist = preprocess_targetlist(tlist,
-									  parse->commandType,
-									  parse->resultRelation,
-									  parse->rtable);
+					      parse->commandType,
+					      parse->resultRelation,
+					      parse->rtable);
 	}
 	else
 	{
-		List	  **vpm = NULL;
-
-		tlist = preprocess_targetlist(tlist,
-									  parse->commandType,
-									  parse->resultRelation,
-									  parse->rtable);
-		if (parse->rtable != NULL)
+	  List  **vpm = NULL;
+	  
+	  /* This is only necessary if aggregates are in use in queries like:
+	   * SELECT sid 
+	   * FROM part
+	   * GROUP BY sid
+	   * HAVING MIN(pid) > 1;  (pid is used but never selected for!!!)
+	   * because the function 'query_planner' creates the plan for the lefttree
+	   * of the 'GROUP' node and returns only those attributes contained in 'tlist'.
+	   * The original 'tlist' contains only 'sid' here and that's why we have to
+	   * to extend it to attributes which are not selected but are used in the 
+	   * havingQual. */
+	  	  
+	  /* 'check_having_qual_for_vars' takes the havingQual and the actual 'tlist'
+	   * as arguments and recursively scans the havingQual for attributes 
+	   * (VAR nodes) that are not contained in 'tlist' yet. If so, it creates
+	   * a new entry and attaches it to the list 'new_tlist' (consisting of the 
+	   * VAR node and the RESDOM node as usual with tlists :-)  ) */
+	  if (parse->hasAggs)
+	    {
+	      if (parse->havingQual != NULL)
 		{
-			vpm = (List **) palloc(length(parse->rtable) * sizeof(List *));
-			memset(vpm, 0, length(parse->rtable) * sizeof(List *));
+		  new_tlist = check_having_qual_for_vars(parse->havingQual,new_tlist);
 		}
-		PlannerVarParam = lcons(vpm, PlannerVarParam);
-		result_plan = query_planner(parse,
-									parse->commandType,
-									tlist,
-									(List *) parse->qual);
-		PlannerVarParam = lnext(PlannerVarParam);
-		if (vpm != NULL)
-			pfree(vpm);
+	    }
+	  
+	  new_tlist = preprocess_targetlist(new_tlist,
+					    parse->commandType,
+					    parse->resultRelation,
+					    parse->rtable);
+	  
+	  /* Here starts the original (pre having) code */
+	  tlist = preprocess_targetlist(tlist,
+					parse->commandType,
+					parse->resultRelation,
+					parse->rtable);
+	  
+	  if (parse->rtable != NULL)
+	    {
+	      vpm = (List **) palloc(length(parse->rtable) * sizeof(List *));
+	      memset(vpm, 0, length(parse->rtable) * sizeof(List *));
+	    }
+	  PlannerVarParam = lcons(vpm, PlannerVarParam);
+	  result_plan = query_planner(parse,
+				      parse->commandType,
+				      new_tlist,
+				      (List *) parse->qual);
+	  PlannerVarParam = lnext(PlannerVarParam);
+	  if (vpm != NULL)
+	    pfree(vpm);		 
 	}
-
+	
 	/*
 	 * If we have a GROUP BY clause, insert a group node (with the
 	 * appropriate sort node.)
@@ -160,12 +196,12 @@ union_planner(Query *parse)
 		 */
 		tuplePerGroup = parse->hasAggs;
 
+		/* Use 'new_tlist' instead of 'tlist' */
 		result_plan =
-			make_groupPlan(&tlist,
+			make_groupPlan(&new_tlist,
 						   tuplePerGroup,
 						   parse->groupClause,
 						   result_plan);
-
 	}
 
 	/*
@@ -173,6 +209,11 @@ union_planner(Query *parse)
 	 */
 	if (parse->hasAggs)
 	{
+	        int old_length=0, new_length=0;
+		
+		/* Create the AGG node but use 'tlist' not 'new_tlist' as target list because we
+		 * don't want the additional attributes (only used for the havingQual, see above)
+		 * to show up in the result */
 		result_plan = (Plan *) make_agg(tlist, result_plan);
 
 		/*
@@ -180,23 +221,71 @@ union_planner(Query *parse)
 		 * the result tuple of the subplans.
 		 */
 		((Agg *) result_plan)->aggs =
-			set_agg_tlist_references((Agg *) result_plan); 
+		  set_agg_tlist_references((Agg *) result_plan); 
 
-		if(parse->havingQual != NULL) {
-		  List	   *clause;
 
-		  /* set qpqual of having clause */
-		  ((Agg *) result_plan)->plan.qual=cnfify((Expr *)parse->havingQual,true);
-
-		  foreach(clause, ((Agg *) result_plan)->plan.qual)
-		    {
-		      ((Agg *) result_plan)->aggs = nconc(((Agg *) result_plan)->aggs,
-			 check_having_qual_for_aggs((Node *) lfirst(clause),
-				       ((Agg *) result_plan)->plan.lefttree->targetlist));
-		    }
-		}
-	}
+		if(parse->havingQual!=NULL) 
+		  {
+		    List	   *clause;
+		    List	  **vpm = NULL;
+		    
+		    
+		    /* stuff copied from above to handle the use of attributes from outside
+		     * in subselects */
 
+		    if (parse->rtable != NULL)
+		      {
+			vpm = (List **) palloc(length(parse->rtable) * sizeof(List *));
+			memset(vpm, 0, length(parse->rtable) * sizeof(List *));
+		      }
+		    PlannerVarParam = lcons(vpm, PlannerVarParam);
+		    
+		    /* There is a subselect in the havingQual, so we have to process it
+                     * using the same function as for a subselect in 'where' */
+		    if (parse->hasSubLinks)
+		      {
+			(List *) parse->havingQual = 
+			  (List *) SS_process_sublinks((Node *) parse->havingQual);
+		      }
+		    		    
+		    /* convert the havingQual to conjunctive normal form (cnf) */
+		    (List *) parse->havingQual=cnfify((Expr *)(Node *) parse->havingQual,true);
+		    
+		    /* Calculate the opfids from the opnos (=select the correct functions for
+		     * the used VAR datatypes) */
+		    (List *) parse->havingQual=fix_opids((List *) parse->havingQual);
+		    
+		    ((Agg *) result_plan)->plan.qual=(List *) parse->havingQual;
+
+		    /* Check every clause of the havingQual for aggregates used and append
+		     * them to result_plan->aggs */
+		    foreach(clause, ((Agg *) result_plan)->plan.qual)
+		      {
+			/* Make sure there are aggregates in the havingQual 
+			 * if so, the list must be longer after check_having_qual_for_aggs */
+			old_length=length(((Agg *) result_plan)->aggs);			
+			
+			((Agg *) result_plan)->aggs = nconc(((Agg *) result_plan)->aggs,
+			    check_having_qual_for_aggs((Node *) lfirst(clause),
+				       ((Agg *) result_plan)->plan.lefttree->targetlist,
+				       ((List *) parse->groupClause)));
+
+			/* Have a look at the length of the returned list. If there is no
+			 * difference, no aggregates have been found and that means, that
+			 * the Qual belongs to the where clause */
+			if (((new_length=length(((Agg *) result_plan)->aggs)) == old_length) ||
+			    (new_length == 0))
+			  {
+			    elog(ERROR,"This could have been done in a where clause!!");
+			    return (Plan *)NIL;
+			  }
+		      }
+		    PlannerVarParam = lnext(PlannerVarParam);
+		    if (vpm != NULL)
+		      pfree(vpm);		
+		  }
+	}		  
+		
 	/*
 	 * For now, before we hand back the plan, check to see if there is a
 	 * user-specified sort that needs to be done.  Eventually, this will
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index c1e3194133b25543b52308cc381ac22de2ca99e1..96b203498ff102dba936c65a39b177c1b9153936 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.22 1998/06/15 19:28:44 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.23 1998/07/19 05:49:15 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -898,12 +898,139 @@ del_agg_clause(Node *clause)
 }
 
 
+/* check_having_qual_for_vars takes the the havingQual and the actual targetlist as arguments
+ * and recursively scans the havingQual for attributes that are not included in the targetlist
+ * yet. Attributes contained in the havingQual but not in the targetlist show up with queries
+ * like: 
+ * SELECT sid 
+ * FROM part
+ * GROUP BY sid
+ * HAVING MIN(pid) > 1;  (pid is used but never selected for!!!). 
+ * To be able to handle queries like that correctly we have to extend the actual targetlist
+ *  (which will be the one used for the GROUP node later on) by these attributes. */
 List *
-check_having_qual_for_aggs(Node *clause, List *subplanTargetList)
+check_having_qual_for_vars(Node *clause, List *targetlist_so_far)
 {
-	List	   *t;
+  List	   *t;
+
+
+  if (IsA(clause, Var))
+    {
+      RelOptInfo         tmp_rel;
+      
+
+      tmp_rel.targetlist = targetlist_so_far;
+      
+      /* 
+       * Ha! A Var node!
+       */
+
+      /* Check if the VAR is already contained in the targetlist */
+      if (tlist_member((Var *)clause, (List *)targetlist_so_far) == NULL)
+	{
+	  add_tl_element(&tmp_rel, (Var *)clause); 
+	} 
+	    
+      return tmp_rel.targetlist;
+    }
+  
+  else if (is_funcclause(clause) || not_clause(clause) || 
+	   or_clause(clause) || and_clause(clause))
+    {
+      
+      /*
+       * This is a function. Recursively call this routine for its
+       * arguments...
+       */
+      foreach(t, ((Expr *) clause)->args)
+	{
+	  targetlist_so_far = check_having_qual_for_vars(lfirst(t), targetlist_so_far);
+	}
+      return targetlist_so_far;
+    }
+  else if (IsA(clause, Aggreg))
+    {
+	  targetlist_so_far = 
+	    check_having_qual_for_vars(((Aggreg *) clause)->target, targetlist_so_far);
+	  return targetlist_so_far;
+    }
+  else if (IsA(clause, ArrayRef))
+    {
+      ArrayRef   *aref = (ArrayRef *) clause;
+      
+      /*
+       * This is an arrayref. Recursively call this routine for its
+       * expression and its index expression...
+       */
+      foreach(t, aref->refupperindexpr)
+	{
+	  targetlist_so_far = check_having_qual_for_vars(lfirst(t), targetlist_so_far);
+	}
+      foreach(t, aref->reflowerindexpr)
+	{
+	  targetlist_so_far = check_having_qual_for_vars(lfirst(t), targetlist_so_far);
+	}
+      targetlist_so_far = check_having_qual_for_vars(aref->refexpr, targetlist_so_far);
+      targetlist_so_far = check_having_qual_for_vars(aref->refassgnexpr, targetlist_so_far);
+      
+      return targetlist_so_far;
+    }
+  else if (is_opclause(clause))
+    {
+      
+      /*
+       * This is an operator. Recursively call this routine for both its
+       * left and right operands
+       */
+      Node	   *left = (Node *) get_leftop((Expr *) clause);
+      Node	   *right = (Node *) get_rightop((Expr *) clause);
+      
+      if (left != (Node *) NULL)
+	targetlist_so_far = check_having_qual_for_vars(left, targetlist_so_far);
+      if (right != (Node *) NULL)
+	targetlist_so_far = check_having_qual_for_vars(right, targetlist_so_far);
+      
+      return targetlist_so_far;
+    }
+  else if (IsA(clause, Param) || IsA(clause, Const))
+    {
+      /* do nothing! */
+      return targetlist_so_far;
+    }
+  /* If we get to a sublink, then we only have to check the lefthand side of the expression
+   * to see if there are any additional VARs */
+  else if (IsA(clause, SubLink))
+    {
+      foreach(t,((List *)((SubLink *)clause)->lefthand))
+	{
+	  targetlist_so_far = check_having_qual_for_vars(lfirst(t), targetlist_so_far);
+	}
+      return targetlist_so_far;
+    }
+  else
+    {
+      /*
+       * Ooops! we can not handle that!
+       */
+      elog(ERROR, "check_having_qual_for_vars: Can not handle this having_qual! %d\n",
+	   nodeTag(clause));
+      return NIL;
+    }
+}
+
+/* check_having_qual_for_aggs takes the havingQual, the targetlist and the groupClause  
+ * as arguments and scans the havingQual recursively for aggregates. If an aggregate is
+ * found it is attached to a list and returned by the function. (All the returned lists 
+ * are concenated to result_plan->aggs in planner.c:union_planner() */
+List *
+check_having_qual_for_aggs(Node *clause, List *subplanTargetList, List *groupClause)
+{
+	List	   *t, *l1;
 	List	   *agg_list = NIL;
 
+	int contained_in_group_clause = 0;
+	
+
 	if (IsA(clause, Var))
 	{
 	  TargetEntry *subplanVar;
@@ -914,32 +1041,50 @@ check_having_qual_for_aggs(Node *clause, List *subplanTargetList)
 	  subplanVar = match_varid((Var *) clause, subplanTargetList);
 	  
 	  /*
-	   * Change the varno & varattno fields of the var node.
-	   *
-	   */
+	   * Change the varno & varattno fields of the var node to point to the resdom->resno
+	   * fields of the subplan (lefttree) 
+	   */	  
 	  ((Var *) clause)->varattno = subplanVar->resdom->resno;
+
 	  return NIL;
+
 	}
 	else if (is_funcclause(clause) || not_clause(clause) || 
 		 or_clause(clause) || and_clause(clause))
 	{
-
+	  int new_length=0, old_length=0;
+	  
 		/*
 		 * This is a function. Recursively call this routine for its
-		 * arguments...
+		 * arguments... (i.e. for AND, OR, ... clauses!)
 		 */
 		foreach(t, ((Expr *) clause)->args)
 		{
-			agg_list = nconc(agg_list,
-					   check_having_qual_for_aggs(lfirst(t), subplanTargetList));
+		  old_length=length((List *)agg_list);
+
+		  agg_list = nconc(agg_list,
+				   check_having_qual_for_aggs(lfirst(t), subplanTargetList,
+							      groupClause));
+
+		  /* The arguments of OR or AND clauses are comparisons or relations 
+		   * and because we are in the havingQual there must be at least one operand
+		   * using an aggregate function. If so, we will find it and the lenght of the
+		   * agg_list will be increased after the above call to 
+		   * check_having_qual_for_aggs. If there are no aggregates used, the query
+                   * could have been formulated using the 'where' clause */
+		  if(((new_length=length((List *)agg_list)) == old_length) || (new_length == 0))
+		    {
+		      elog(ERROR,"This could have been done in a where clause!!");
+		      return NIL;
+		    } 
 		}
 		return agg_list;
 	}
 	else if (IsA(clause, Aggreg))
 	{
 		return lcons(clause,
-		    check_having_qual_for_aggs(((Aggreg *) clause)->target, subplanTargetList));
-		
+		    check_having_qual_for_aggs(((Aggreg *) clause)->target, subplanTargetList,
+					       groupClause));		
 	}
 	else if (IsA(clause, ArrayRef))
 	{
@@ -952,17 +1097,21 @@ check_having_qual_for_aggs(Node *clause, List *subplanTargetList)
 		foreach(t, aref->refupperindexpr)
 		{
 			agg_list = nconc(agg_list,
-					 check_having_qual_for_aggs(lfirst(t), subplanTargetList));
+					 check_having_qual_for_aggs(lfirst(t), subplanTargetList,
+								    groupClause));
 		}
 		foreach(t, aref->reflowerindexpr)
 		{
 			agg_list = nconc(agg_list,
-					 check_having_qual_for_aggs(lfirst(t), subplanTargetList));
+					 check_having_qual_for_aggs(lfirst(t), subplanTargetList,
+								    groupClause));
 		}
 		agg_list = nconc(agg_list,
-				 check_having_qual_for_aggs(aref->refexpr, subplanTargetList));
+				 check_having_qual_for_aggs(aref->refexpr, subplanTargetList,
+							    groupClause));
 		agg_list = nconc(agg_list,
-				 check_having_qual_for_aggs(aref->refassgnexpr, subplanTargetList));
+				 check_having_qual_for_aggs(aref->refassgnexpr, subplanTargetList,
+							    groupClause));
 
 		return agg_list;
 	}
@@ -978,27 +1127,79 @@ check_having_qual_for_aggs(Node *clause, List *subplanTargetList)
 
 		if (left != (Node *) NULL)
 			agg_list = nconc(agg_list,
-					 check_having_qual_for_aggs(left, subplanTargetList));
+					 check_having_qual_for_aggs(left, subplanTargetList,
+								    groupClause));
 		if (right != (Node *) NULL)
 			agg_list = nconc(agg_list,
-					 check_having_qual_for_aggs(right, subplanTargetList));
+					 check_having_qual_for_aggs(right, subplanTargetList,
+								    groupClause));
 
 		return agg_list;
 	}
-	else if (IsA(clause, Param) ||IsA(clause, Const))
+	else if (IsA(clause, Param) || IsA(clause, Const))
 	{
 		/* do nothing! */
 		return NIL;
 	}
+	/* This is for Sublinks which show up as EXPR nodes. All the other EXPR nodes
+         * (funcclauses, and_clauses, or_clauses) were caught above */
+	else if (IsA(clause, Expr))
+	  {
+	    /* Only the lefthand side of the sublink has to be checked for aggregates
+             * to be attached to result_plan->aggs (see planner.c:union_planner() )
+	     */	    
+	    foreach(t,((List *)((SubLink *)((SubPlan *)
+		       ((Expr *)clause)->oper)->sublink)->lefthand)) 
+	      {
+		agg_list = 
+		  nconc(agg_list,
+			check_having_qual_for_aggs(lfirst(t), 
+						   subplanTargetList, groupClause));
+	      }
+	    
+		
+	    /* All arguments to the Sublink node are attributes from outside used within
+	     * the sublink. Here we have to check that only attributes that is grouped for
+	     * are used! */
+	    foreach(t,((Expr *)clause)->args) 
+	      {	
+		contained_in_group_clause = 0;
+
+		foreach(l1,groupClause)
+		  {
+		    if (tlist_member(lfirst(t),lcons(((GroupClause *)lfirst(l1))->entry,NIL)) != 
+			NULL)
+		      {
+			contained_in_group_clause=1;
+		      }
+		  }
+		
+		/* If the use of the attribute is allowed (i.e. it is in the groupClause)
+		 * we have to adjust the varnos and varattnos */
+		if (contained_in_group_clause)
+		  {
+		    agg_list = 
+		      nconc(agg_list,
+			    check_having_qual_for_aggs(lfirst(t), 
+						       subplanTargetList, groupClause));
+		  }
+		else
+		  {
+		    elog(ERROR,"You must group by the attribute used from outside!");
+		    return NIL;
+		  }		
+	      }
+	    return agg_list;
+	  }
 	else
-	{
-
-		/*
-		 * Ooops! we can not handle that!
-		 */
-		elog(ERROR, "check_having_qual_for_aggs: Can not handle this having_qual!\n");
-		return NIL;
-	}
+	  {
+	    /*
+	     * Ooops! we can not handle that!
+	     */
+	    elog(ERROR, "check_having_qual_for_aggs: Can not handle this having_qual! %d\n",
+		 nodeTag(clause));
+	    return NIL;
+	  }
 }
 
 
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 72d023dccf5a0f5ee3b83355b2c324b935dca7ed..040c6732ccc1aa4b411fe8869f3385a5a8ea356e 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -404,8 +404,13 @@ SS_process_sublinks(Node *expr)
 		((Expr *) expr)->args = (List *)
 			SS_process_sublinks((Node *) ((Expr *) expr)->args);
 	else if (IsA(expr, SubLink))/* got it! */
-		expr = _make_subplan((SubLink *) expr);
+	  {
+	    lfirst(((Expr *) lfirst(((SubLink *)expr)->oper))->args) = 
+				  lfirst(((SubLink *)expr)->lefthand);
 
+	    expr = _make_subplan((SubLink *) expr);
+	  }
+	
 	return (expr);
 }
 
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 95e19e8cb59a3b1394f464354e75f5f9e55a6a08..4865d2de6daae8093c653f13db052515dfa85961 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.76 1998/05/29 13:39:30 thomas Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.77 1998/07/19 05:49:17 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -327,6 +327,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
 	/* fix where clause */
 	qry->qual = transformWhereClause(pstate, stmt->whereClause);
 
+	/* The havingQual has a similar meaning as "qual" in the where statement. 
+	 * So we can easily use the code from the "where clause" with some additional
+         * traversals done in .../optimizer/plan/planner.c */
 	qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
 
 	qry->hasSubLinks = pstate->p_hasSubLinks;
@@ -356,6 +359,15 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
 	qry->unionall = stmt->unionall;
 	qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
 
+	/* If there is a havingQual but there are no aggregates, then there is something wrong
+	 * with the query because having must contain aggregates in its expressions! 
+	 * Otherwise the query could have been formulated using the where clause. */
+	if((qry->hasAggs == false) && (qry->havingQual != NULL))
+	  {
+	    elog(ERROR,"This is not a valid having query!");
+	    return (Query *)NIL;
+	  }
+
 	return (Query *) qry;
 }
 
@@ -795,6 +807,9 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
 
 	qry->qual = transformWhereClause(pstate, stmt->whereClause);
 
+	/* The havingQual has a similar meaning as "qual" in the where statement. 
+	 * So we can easily use the code from the "where clause" with some additional
+         * traversals done in .../optimizer/plan/planner.c */
 	qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
 
 	qry->hasSubLinks = pstate->p_hasSubLinks;
@@ -820,6 +835,15 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
 	qry->unionall = stmt->unionall;
 	qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
 
+	/* If there is a havingQual but there are no aggregates, then there is something wrong
+	 * with the query because having must contain aggregates in its expressions! 
+	 * Otherwise the query could have been formulated using the where clause. */
+	if((qry->hasAggs == false) && (qry->havingQual != NULL))
+	  {
+	    elog(ERROR,"This is not a valid having query!");
+	    return (Query *)NIL;
+	  }
+
 	return (Query *) qry;
 }
 
diff --git a/src/backend/parser/gram.c b/src/backend/parser/gram.c
index fa1e1cef6cb7e6f8bb379f2b80d39c210933b7aa..670e052257f9d2d2fa97b80dae79982f71edb2a2 100644
--- a/src/backend/parser/gram.c
+++ b/src/backend/parser/gram.c
@@ -218,7 +218,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/Attic/gram.c,v 2.16 1998/07/15 22:16:18 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/Attic/gram.c,v 2.17 1998/07/19 05:49:18 momjian Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -795,45 +795,45 @@ static const short yyrline[] = { 0,
   2434,  2440,  2444,  2462,  2463,  2466,  2467,  2470,  2471,  2474,
   2475,  2476,  2477,  2480,  2481,  2484,  2485,  2488,  2496,  2504,
   2514,  2515,  2516,  2517,  2518,  2519,  2529,  2530,  2533,  2535,
-  2537,  2541,  2542,  2545,  2546,  2549,  2557,  2565,  2575,  2582,
-  2594,  2599,  2600,  2603,  2605,  2607,  2611,  2617,  2623,  2631,
-  2632,  2634,  2636,  2638,  2640,  2642,  2644,  2648,  2649,  2652,
-  2653,  2654,  2657,  2658,  2661,  2669,  2677,  2687,  2688,  2691,
-  2698,  2706,  2708,  2710,  2714,  2716,  2718,  2733,  2755,  2756,
-  2763,  2764,  2765,  2768,  2776,  2777,  2786,  2792,  2797,  2803,
-  2811,  2813,  2815,  2817,  2821,  2832,  2838,  2845,  2850,  2856,
-  2864,  2870,  2883,  2910,  2929,  2949,  2950,  2951,  2952,  2955,
-  2956,  2959,  2960,  2963,  2964,  2967,  2973,  2980,  2986,  2994,
-  2995,  2996,  2997,  2998,  2999,  3002,  3003,  3006,  3007,  3008,
-  3009,  3010,  3011,  3012,  3013,  3014,  3024,  3026,  3043,  3053,
-  3063,  3076,  3089,  3095,  3101,  3105,  3111,  3112,  3113,  3114,
-  3115,  3116,  3117,  3118,  3121,  3122,  3133,  3138,  3140,  3142,
-  3150,  3152,  3154,  3156,  3158,  3160,  3162,  3164,  3166,  3168,
-  3170,  3172,  3188,  3204,  3206,  3208,  3210,  3212,  3214,  3216,
-  3228,  3235,  3242,  3257,  3272,  3294,  3309,  3331,  3338,  3345,
-  3355,  3362,  3369,  3377,  3384,  3391,  3398,  3405,  3407,  3409,
-  3411,  3418,  3428,  3438,  3448,  3458,  3464,  3470,  3470,  3484,
-  3484,  3498,  3508,  3518,  3528,  3538,  3548,  3558,  3568,  3578,
-  3588,  3598,  3608,  3618,  3628,  3638,  3648,  3658,  3668,  3678,
-  3688,  3698,  3708,  3718,  3728,  3738,  3740,  3742,  3752,  3757,
-  3759,  3767,  3769,  3771,  3773,  3775,  3777,  3779,  3781,  3783,
-  3799,  3815,  3817,  3819,  3821,  3823,  3830,  3837,  3852,  3867,
-  3889,  3904,  3926,  3933,  3940,  3947,  3955,  3962,  3969,  3976,
-  3985,  3992,  3999,  4003,  4005,  4007,  4011,  4018,  4022,  4023,
-  4024,  4027,  4029,  4033,  4038,  4040,  4042,  4044,  4046,  4048,
-  4050,  4052,  4068,  4084,  4086,  4088,  4090,  4092,  4100,  4107,
-  4114,  4121,  4129,  4136,  4143,  4150,  4159,  4163,  4167,  4169,
-  4178,  4180,  4184,  4186,  4188,  4192,  4198,  4202,  4204,  4210,
-  4216,  4220,  4222,  4228,  4236,  4246,  4248,  4250,  4261,  4263,
-  4265,  4280,  4287,  4294,  4313,  4315,  4320,  4327,  4334,  4346,
-  4360,  4361,  4364,  4369,  4381,  4382,  4383,  4384,  4385,  4391,
-  4392,  4394,  4395,  4400,  4407,  4414,  4421,  4429,  4431,  4441,
-  4453,  4460,  4461,  4462,  4469,  4471,  4473,  4484,  4485,  4486,
-  4487,  4488,  4489,  4490,  4491,  4492,  4493,  4494,  4495,  4496,
-  4497,  4498,  4499,  4500,  4501,  4502,  4503,  4504,  4505,  4506,
-  4507,  4508,  4509,  4510,  4511,  4512,  4513,  4514,  4515,  4516,
-  4517,  4530,  4531,  4532,  4533,  4534,  4535,  4536,  4537,  4538,
-  4539,  4540,  4541,  4542,  4543,  4544,  4547,  4554
+  2537,  2541,  2542,  2545,  2546,  2549,  2557,  2565,  2575,  2579,
+  2591,  2596,  2597,  2600,  2602,  2604,  2608,  2614,  2620,  2628,
+  2629,  2631,  2633,  2635,  2637,  2639,  2641,  2645,  2646,  2649,
+  2650,  2651,  2654,  2655,  2658,  2666,  2674,  2684,  2685,  2688,
+  2695,  2703,  2705,  2707,  2711,  2713,  2715,  2730,  2752,  2753,
+  2760,  2761,  2762,  2765,  2773,  2774,  2783,  2789,  2794,  2800,
+  2808,  2810,  2812,  2814,  2818,  2829,  2835,  2842,  2847,  2853,
+  2861,  2867,  2880,  2907,  2926,  2946,  2947,  2948,  2949,  2952,
+  2953,  2956,  2957,  2960,  2961,  2964,  2970,  2977,  2983,  2991,
+  2992,  2993,  2994,  2995,  2996,  2999,  3000,  3003,  3004,  3005,
+  3006,  3007,  3008,  3009,  3010,  3011,  3021,  3023,  3040,  3050,
+  3060,  3073,  3086,  3092,  3098,  3102,  3108,  3109,  3110,  3111,
+  3112,  3113,  3114,  3115,  3118,  3119,  3130,  3135,  3137,  3139,
+  3147,  3149,  3151,  3153,  3155,  3157,  3159,  3161,  3163,  3165,
+  3167,  3169,  3185,  3201,  3203,  3205,  3207,  3209,  3211,  3213,
+  3225,  3232,  3239,  3254,  3269,  3291,  3306,  3328,  3335,  3342,
+  3352,  3359,  3366,  3374,  3381,  3388,  3395,  3402,  3404,  3406,
+  3408,  3415,  3425,  3435,  3445,  3455,  3461,  3467,  3467,  3481,
+  3481,  3495,  3505,  3515,  3525,  3535,  3545,  3555,  3565,  3575,
+  3585,  3595,  3605,  3615,  3625,  3635,  3645,  3655,  3665,  3675,
+  3685,  3695,  3705,  3715,  3725,  3735,  3737,  3739,  3749,  3754,
+  3756,  3764,  3766,  3768,  3770,  3772,  3774,  3776,  3778,  3780,
+  3796,  3812,  3814,  3816,  3818,  3820,  3827,  3834,  3849,  3864,
+  3886,  3901,  3923,  3930,  3937,  3944,  3952,  3959,  3966,  3973,
+  3982,  3989,  3996,  4000,  4002,  4004,  4008,  4015,  4019,  4020,
+  4021,  4024,  4026,  4030,  4035,  4037,  4039,  4041,  4043,  4045,
+  4047,  4049,  4065,  4081,  4083,  4085,  4087,  4089,  4097,  4104,
+  4111,  4118,  4126,  4133,  4140,  4147,  4156,  4160,  4164,  4166,
+  4175,  4177,  4181,  4183,  4185,  4189,  4195,  4199,  4201,  4207,
+  4213,  4217,  4219,  4225,  4233,  4243,  4245,  4247,  4258,  4260,
+  4262,  4277,  4284,  4291,  4310,  4312,  4317,  4324,  4331,  4343,
+  4357,  4358,  4361,  4366,  4378,  4379,  4380,  4381,  4382,  4388,
+  4389,  4391,  4392,  4397,  4404,  4411,  4418,  4426,  4428,  4438,
+  4450,  4457,  4458,  4459,  4466,  4468,  4470,  4481,  4482,  4483,
+  4484,  4485,  4486,  4487,  4488,  4489,  4490,  4491,  4492,  4493,
+  4494,  4495,  4496,  4497,  4498,  4499,  4500,  4501,  4502,  4503,
+  4504,  4505,  4506,  4507,  4508,  4509,  4510,  4511,  4512,  4513,
+  4514,  4527,  4528,  4529,  4530,  4531,  4532,  4533,  4534,  4535,
+  4536,  4537,  4538,  4539,  4540,  4541,  4544,  4551
 };
 #endif
 
@@ -6907,45 +6907,42 @@ case 468:
 case 469:
 #line 2576 "gram.y"
 {
-#if FALSE
-					elog(ERROR,"HAVING clause not yet implemented");
-#endif
 					yyval.node = yyvsp[0].node;
 				;
     break;}
 case 470:
-#line 2582 "gram.y"
+#line 2579 "gram.y"
 { yyval.node = NULL; ;
     break;}
 case 471:
-#line 2595 "gram.y"
+#line 2592 "gram.y"
 {
 					yyval.list = NIL;
 					elog(ERROR,"JOIN not yet implemented");
 				;
     break;}
 case 472:
-#line 2599 "gram.y"
+#line 2596 "gram.y"
 { yyval.list = yyvsp[0].list; ;
     break;}
 case 473:
-#line 2600 "gram.y"
+#line 2597 "gram.y"
 { yyval.list = NIL; ;
     break;}
 case 474:
-#line 2604 "gram.y"
+#line 2601 "gram.y"
 { yyval.list = lappend(yyvsp[-2].list, yyvsp[0].range); ;
     break;}
 case 475:
-#line 2606 "gram.y"
+#line 2603 "gram.y"
 { elog(ERROR,"CROSS JOIN not yet implemented"); ;
     break;}
 case 476:
-#line 2608 "gram.y"
+#line 2605 "gram.y"
 { yyval.list = lcons(yyvsp[0].range, NIL); ;
     break;}
 case 477:
-#line 2612 "gram.y"
+#line 2609 "gram.y"
 {
 					yyval.range = makeNode(RangeVar);
 					yyval.range->relExpr = yyvsp[-2].relexp;
@@ -6953,7 +6950,7 @@ case 477:
 				;
     break;}
 case 478:
-#line 2618 "gram.y"
+#line 2615 "gram.y"
 {
 					yyval.range = makeNode(RangeVar);
 					yyval.range->relExpr = yyvsp[-1].relexp;
@@ -6961,7 +6958,7 @@ case 478:
 				;
     break;}
 case 479:
-#line 2624 "gram.y"
+#line 2621 "gram.y"
 {
 					yyval.range = makeNode(RangeVar);
 					yyval.range->relExpr = yyvsp[0].relexp;
@@ -6969,67 +6966,67 @@ case 479:
 				;
     break;}
 case 480:
-#line 2631 "gram.y"
+#line 2628 "gram.y"
 { yyval.str = NULL; ;
     break;}
 case 481:
-#line 2633 "gram.y"
+#line 2630 "gram.y"
 { elog(ERROR,"FULL OUTER JOIN not yet implemented"); ;
     break;}
 case 482:
-#line 2635 "gram.y"
+#line 2632 "gram.y"
 { elog(ERROR,"LEFT OUTER JOIN not yet implemented"); ;
     break;}
 case 483:
-#line 2637 "gram.y"
+#line 2634 "gram.y"
 { elog(ERROR,"RIGHT OUTER JOIN not yet implemented"); ;
     break;}
 case 484:
-#line 2639 "gram.y"
+#line 2636 "gram.y"
 { elog(ERROR,"OUTER JOIN not yet implemented"); ;
     break;}
 case 485:
-#line 2641 "gram.y"
+#line 2638 "gram.y"
 { elog(ERROR,"INNER JOIN not yet implemented"); ;
     break;}
 case 486:
-#line 2643 "gram.y"
+#line 2640 "gram.y"
 { elog(ERROR,"UNION JOIN not yet implemented"); ;
     break;}
 case 487:
-#line 2645 "gram.y"
+#line 2642 "gram.y"
 { elog(ERROR,"INNER JOIN not yet implemented"); ;
     break;}
 case 488:
-#line 2648 "gram.y"
+#line 2645 "gram.y"
 { yyval.str = NULL; ;
     break;}
 case 489:
-#line 2649 "gram.y"
+#line 2646 "gram.y"
 { yyval.str = NULL;  /* no qualifiers */ ;
     break;}
 case 490:
-#line 2652 "gram.y"
+#line 2649 "gram.y"
 { yyval.str = NULL; ;
     break;}
 case 491:
-#line 2653 "gram.y"
+#line 2650 "gram.y"
 { yyval.str = NULL; ;
     break;}
 case 492:
-#line 2654 "gram.y"
+#line 2651 "gram.y"
 { yyval.str = NULL;  /* no qualifiers */ ;
     break;}
 case 493:
-#line 2657 "gram.y"
+#line 2654 "gram.y"
 { yyval.list = lcons(yyvsp[0].sortgroupby, NIL); ;
     break;}
 case 494:
-#line 2658 "gram.y"
+#line 2655 "gram.y"
 { yyval.list = lappend(yyvsp[-2].list, yyvsp[0].sortgroupby); ;
     break;}
 case 495:
-#line 2662 "gram.y"
+#line 2659 "gram.y"
 {
 					yyval.sortgroupby = makeNode(SortGroupBy);
 					yyval.sortgroupby->resno = 0;
@@ -7039,7 +7036,7 @@ case 495:
 				;
     break;}
 case 496:
-#line 2670 "gram.y"
+#line 2667 "gram.y"
 {
 					yyval.sortgroupby = makeNode(SortGroupBy);
 					yyval.sortgroupby->resno = 0;
@@ -7049,7 +7046,7 @@ case 496:
 				;
     break;}
 case 497:
-#line 2678 "gram.y"
+#line 2675 "gram.y"
 {
 					yyval.sortgroupby = makeNode(SortGroupBy);
 					yyval.sortgroupby->resno = yyvsp[0].ival;
@@ -7059,15 +7056,15 @@ case 497:
 				;
     break;}
 case 498:
-#line 2687 "gram.y"
+#line 2684 "gram.y"
 { yyval.node = yyvsp[0].node; ;
     break;}
 case 499:
-#line 2688 "gram.y"
+#line 2685 "gram.y"
 { yyval.node = NULL;  /* no qualifiers */ ;
     break;}
 case 500:
-#line 2692 "gram.y"
+#line 2689 "gram.y"
 {
 					/* normal relations */
 					yyval.relexp = makeNode(RelExpr);
@@ -7076,7 +7073,7 @@ case 500:
 				;
     break;}
 case 501:
-#line 2699 "gram.y"
+#line 2696 "gram.y"
 {
 					/* inheritance query */
 					yyval.relexp = makeNode(RelExpr);
@@ -7085,31 +7082,31 @@ case 501:
 				;
     break;}
 case 502:
-#line 2707 "gram.y"
+#line 2704 "gram.y"
 {  yyval.list = lcons(makeInteger(-1), yyvsp[0].list); ;
     break;}
 case 503:
-#line 2709 "gram.y"
+#line 2706 "gram.y"
 {  yyval.list = lcons(makeInteger(yyvsp[-2].ival), yyvsp[0].list); ;
     break;}
 case 504:
-#line 2711 "gram.y"
+#line 2708 "gram.y"
 {  yyval.list = NIL; ;
     break;}
 case 505:
-#line 2715 "gram.y"
+#line 2712 "gram.y"
 {  yyval.list = lcons(makeInteger(-1), yyvsp[0].list); ;
     break;}
 case 506:
-#line 2717 "gram.y"
+#line 2714 "gram.y"
 {  yyval.list = lcons(makeInteger(yyvsp[-2].ival), yyvsp[0].list); ;
     break;}
 case 507:
-#line 2719 "gram.y"
+#line 2716 "gram.y"
 {  yyval.list = NIL; ;
     break;}
 case 508:
-#line 2734 "gram.y"
+#line 2731 "gram.y"
 {
 					yyval.typnam = yyvsp[-1].typnam;
 					yyval.typnam->arrayBounds = yyvsp[0].list;
@@ -7133,14 +7130,14 @@ case 508:
 				;
     break;}
 case 510:
-#line 2757 "gram.y"
+#line 2754 "gram.y"
 {
 					yyval.typnam = yyvsp[0].typnam;
 					yyval.typnam->setof = TRUE;
 				;
     break;}
 case 514:
-#line 2769 "gram.y"
+#line 2766 "gram.y"
 {
 					yyval.typnam = makeNode(TypeName);
 					yyval.typnam->name = xlateSqlType(yyvsp[0].str);
@@ -7148,15 +7145,15 @@ case 514:
 				;
     break;}
 case 515:
-#line 2776 "gram.y"
+#line 2773 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 516:
-#line 2777 "gram.y"
+#line 2774 "gram.y"
 { yyval.str = xlateSqlType("type"); ;
     break;}
 case 517:
-#line 2787 "gram.y"
+#line 2784 "gram.y"
 {
 					yyval.typnam = makeNode(TypeName);
 					yyval.typnam->name = xlateSqlType(yyvsp[0].str);
@@ -7164,14 +7161,14 @@ case 517:
 				;
     break;}
 case 518:
-#line 2793 "gram.y"
+#line 2790 "gram.y"
 {
 					yyval.typnam = makeNode(TypeName);
 					yyval.typnam->name = xlateSqlType("float");
 				;
     break;}
 case 519:
-#line 2798 "gram.y"
+#line 2795 "gram.y"
 {
 					yyval.typnam = makeNode(TypeName);
 					yyval.typnam->name = xlateSqlType("integer");
@@ -7179,7 +7176,7 @@ case 519:
 				;
     break;}
 case 520:
-#line 2804 "gram.y"
+#line 2801 "gram.y"
 {
 					yyval.typnam = makeNode(TypeName);
 					yyval.typnam->name = xlateSqlType("integer");
@@ -7187,23 +7184,23 @@ case 520:
 				;
     break;}
 case 521:
-#line 2812 "gram.y"
+#line 2809 "gram.y"
 {	yyval.str = xlateSqlType("float8"); ;
     break;}
 case 522:
-#line 2814 "gram.y"
+#line 2811 "gram.y"
 {	yyval.str = xlateSqlType("float8"); ;
     break;}
 case 523:
-#line 2816 "gram.y"
+#line 2813 "gram.y"
 {	yyval.str = xlateSqlType("decimal"); ;
     break;}
 case 524:
-#line 2818 "gram.y"
+#line 2815 "gram.y"
 {	yyval.str = xlateSqlType("numeric"); ;
     break;}
 case 525:
-#line 2822 "gram.y"
+#line 2819 "gram.y"
 {
 					if (yyvsp[-1].ival < 1)
 						elog(ERROR,"precision for FLOAT must be at least 1");
@@ -7216,13 +7213,13 @@ case 525:
 				;
     break;}
 case 526:
-#line 2833 "gram.y"
+#line 2830 "gram.y"
 {
 					yyval.str = xlateSqlType("float8");
 				;
     break;}
 case 527:
-#line 2839 "gram.y"
+#line 2836 "gram.y"
 {
 					if (yyvsp[-3].ival != 9)
 						elog(ERROR,"NUMERIC precision %d must be 9",yyvsp[-3].ival);
@@ -7231,20 +7228,20 @@ case 527:
 				;
     break;}
 case 528:
-#line 2846 "gram.y"
+#line 2843 "gram.y"
 {
 					if (yyvsp[-1].ival != 9)
 						elog(ERROR,"NUMERIC precision %d must be 9",yyvsp[-1].ival);
 				;
     break;}
 case 529:
-#line 2851 "gram.y"
+#line 2848 "gram.y"
 {
 					yyval.str = NULL;
 				;
     break;}
 case 530:
-#line 2857 "gram.y"
+#line 2854 "gram.y"
 {
 					if (yyvsp[-3].ival > 9)
 						elog(ERROR,"DECIMAL precision %d exceeds implementation limit of 9",yyvsp[-3].ival);
@@ -7254,7 +7251,7 @@ case 530:
 				;
     break;}
 case 531:
-#line 2865 "gram.y"
+#line 2862 "gram.y"
 {
 					if (yyvsp[-1].ival > 9)
 						elog(ERROR,"DECIMAL precision %d exceeds implementation limit of 9",yyvsp[-1].ival);
@@ -7262,13 +7259,13 @@ case 531:
 				;
     break;}
 case 532:
-#line 2871 "gram.y"
+#line 2868 "gram.y"
 {
 					yyval.str = NULL;
 				;
     break;}
 case 533:
-#line 2884 "gram.y"
+#line 2881 "gram.y"
 {
 					yyval.typnam = makeNode(TypeName);
 					if (strcasecmp(yyvsp[-3].str, "char") == 0)
@@ -7297,7 +7294,7 @@ case 533:
 				;
     break;}
 case 534:
-#line 2911 "gram.y"
+#line 2908 "gram.y"
 {
 					yyval.typnam = makeNode(TypeName);
 					/* Let's try to make all single-character types into bpchar(1)
@@ -7316,7 +7313,7 @@ case 534:
 				;
     break;}
 case 535:
-#line 2930 "gram.y"
+#line 2927 "gram.y"
 {
 					char *type, *c;
 					if ((yyvsp[-1].str == NULL) || (strcasecmp(yyvsp[-1].str, "sql_text") == 0)) {
@@ -7338,47 +7335,47 @@ case 535:
 				;
     break;}
 case 536:
-#line 2949 "gram.y"
+#line 2946 "gram.y"
 { yyval.str = xlateSqlType(yyvsp[0].boolean? "varchar": "char"); ;
     break;}
 case 537:
-#line 2950 "gram.y"
+#line 2947 "gram.y"
 { yyval.str = xlateSqlType("varchar"); ;
     break;}
 case 538:
-#line 2951 "gram.y"
+#line 2948 "gram.y"
 { yyval.str = xlateSqlType(yyvsp[0].boolean? "varchar": "char"); ;
     break;}
 case 539:
-#line 2952 "gram.y"
+#line 2949 "gram.y"
 { yyval.str = xlateSqlType(yyvsp[0].boolean? "varchar": "char"); ;
     break;}
 case 540:
-#line 2955 "gram.y"
+#line 2952 "gram.y"
 { yyval.boolean = TRUE; ;
     break;}
 case 541:
-#line 2956 "gram.y"
+#line 2953 "gram.y"
 { yyval.boolean = FALSE; ;
     break;}
 case 542:
-#line 2959 "gram.y"
+#line 2956 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 543:
-#line 2960 "gram.y"
+#line 2957 "gram.y"
 { yyval.str = NULL; ;
     break;}
 case 544:
-#line 2963 "gram.y"
+#line 2960 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 545:
-#line 2964 "gram.y"
+#line 2961 "gram.y"
 { yyval.str = NULL; ;
     break;}
 case 546:
-#line 2968 "gram.y"
+#line 2965 "gram.y"
 {
 					yyval.typnam = makeNode(TypeName);
 					yyval.typnam->name = xlateSqlType(yyvsp[0].str);
@@ -7386,7 +7383,7 @@ case 546:
 				;
     break;}
 case 547:
-#line 2974 "gram.y"
+#line 2971 "gram.y"
 {
 					yyval.typnam = makeNode(TypeName);
 					yyval.typnam->name = xlateSqlType("timestamp");
@@ -7395,7 +7392,7 @@ case 547:
 				;
     break;}
 case 548:
-#line 2981 "gram.y"
+#line 2978 "gram.y"
 {
 					yyval.typnam = makeNode(TypeName);
 					yyval.typnam->name = xlateSqlType("time");
@@ -7403,7 +7400,7 @@ case 548:
 				;
     break;}
 case 549:
-#line 2987 "gram.y"
+#line 2984 "gram.y"
 {
 					yyval.typnam = makeNode(TypeName);
 					yyval.typnam->name = xlateSqlType("interval");
@@ -7411,79 +7408,79 @@ case 549:
 				;
     break;}
 case 550:
-#line 2994 "gram.y"
+#line 2991 "gram.y"
 { yyval.str = "year"; ;
     break;}
 case 551:
-#line 2995 "gram.y"
+#line 2992 "gram.y"
 { yyval.str = "month"; ;
     break;}
 case 552:
-#line 2996 "gram.y"
+#line 2993 "gram.y"
 { yyval.str = "day"; ;
     break;}
 case 553:
-#line 2997 "gram.y"
+#line 2994 "gram.y"
 { yyval.str = "hour"; ;
     break;}
 case 554:
-#line 2998 "gram.y"
+#line 2995 "gram.y"
 { yyval.str = "minute"; ;
     break;}
 case 555:
-#line 2999 "gram.y"
+#line 2996 "gram.y"
 { yyval.str = "second"; ;
     break;}
 case 556:
-#line 3002 "gram.y"
+#line 2999 "gram.y"
 { yyval.boolean = TRUE; ;
     break;}
 case 557:
-#line 3003 "gram.y"
+#line 3000 "gram.y"
 { yyval.boolean = FALSE; ;
     break;}
 case 558:
-#line 3006 "gram.y"
+#line 3003 "gram.y"
 { yyval.list = lcons(yyvsp[0].str, NIL); ;
     break;}
 case 559:
-#line 3007 "gram.y"
+#line 3004 "gram.y"
 { yyval.list = NIL; ;
     break;}
 case 560:
-#line 3008 "gram.y"
+#line 3005 "gram.y"
 { yyval.list = NIL; ;
     break;}
 case 561:
-#line 3009 "gram.y"
+#line 3006 "gram.y"
 { yyval.list = NIL; ;
     break;}
 case 562:
-#line 3010 "gram.y"
+#line 3007 "gram.y"
 { yyval.list = NIL; ;
     break;}
 case 563:
-#line 3011 "gram.y"
+#line 3008 "gram.y"
 { yyval.list = NIL; ;
     break;}
 case 564:
-#line 3012 "gram.y"
+#line 3009 "gram.y"
 { yyval.list = NIL; ;
     break;}
 case 565:
-#line 3013 "gram.y"
+#line 3010 "gram.y"
 { yyval.list = NIL; ;
     break;}
 case 566:
-#line 3014 "gram.y"
+#line 3011 "gram.y"
 { yyval.list = NIL; ;
     break;}
 case 567:
-#line 3025 "gram.y"
+#line 3022 "gram.y"
 { yyval.node = yyvsp[0].node; ;
     break;}
 case 568:
-#line 3027 "gram.y"
+#line 3024 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					n->val.type = T_Null;
@@ -7491,7 +7488,7 @@ case 568:
 				;
     break;}
 case 569:
-#line 3044 "gram.y"
+#line 3041 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = yyvsp[-5].list;
@@ -7503,7 +7500,7 @@ case 569:
 				;
     break;}
 case 570:
-#line 3054 "gram.y"
+#line 3051 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = yyvsp[-6].list;
@@ -7515,7 +7512,7 @@ case 570:
 				;
     break;}
 case 571:
-#line 3064 "gram.y"
+#line 3061 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = yyvsp[-6].list;
@@ -7530,7 +7527,7 @@ case 571:
 				;
     break;}
 case 572:
-#line 3077 "gram.y"
+#line 3074 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = yyvsp[-5].list;
@@ -7545,86 +7542,86 @@ case 572:
 				;
     break;}
 case 573:
-#line 3090 "gram.y"
+#line 3087 "gram.y"
 {
 					yyval.node = makeRowExpr(yyvsp[-3].str, yyvsp[-5].list, yyvsp[-1].list);
 				;
     break;}
 case 574:
-#line 3096 "gram.y"
+#line 3093 "gram.y"
 {
 					yyval.list = lappend(yyvsp[-2].list, yyvsp[0].node);
 				;
     break;}
 case 575:
-#line 3102 "gram.y"
+#line 3099 "gram.y"
 {
 					yyval.list = lappend(yyvsp[-2].list, yyvsp[0].node);
 				;
     break;}
 case 576:
-#line 3106 "gram.y"
+#line 3103 "gram.y"
 {
 					yyval.list = lcons(yyvsp[0].node, NIL);
 				;
     break;}
 case 577:
-#line 3111 "gram.y"
+#line 3108 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 578:
-#line 3112 "gram.y"
+#line 3109 "gram.y"
 { yyval.str = "<"; ;
     break;}
 case 579:
-#line 3113 "gram.y"
+#line 3110 "gram.y"
 { yyval.str = "="; ;
     break;}
 case 580:
-#line 3114 "gram.y"
+#line 3111 "gram.y"
 { yyval.str = ">"; ;
     break;}
 case 581:
-#line 3115 "gram.y"
+#line 3112 "gram.y"
 { yyval.str = "+"; ;
     break;}
 case 582:
-#line 3116 "gram.y"
+#line 3113 "gram.y"
 { yyval.str = "-"; ;
     break;}
 case 583:
-#line 3117 "gram.y"
+#line 3114 "gram.y"
 { yyval.str = "*"; ;
     break;}
 case 584:
-#line 3118 "gram.y"
+#line 3115 "gram.y"
 { yyval.str = "/"; ;
     break;}
 case 585:
-#line 3121 "gram.y"
+#line 3118 "gram.y"
 { yyval.ival = ANY_SUBLINK; ;
     break;}
 case 586:
-#line 3122 "gram.y"
+#line 3119 "gram.y"
 { yyval.ival = ALL_SUBLINK; ;
     break;}
 case 587:
-#line 3134 "gram.y"
+#line 3131 "gram.y"
 {
 					yyvsp[-1].attr->indirection = yyvsp[0].list;
 					yyval.node = (Node *)yyvsp[-1].attr;
 				;
     break;}
 case 588:
-#line 3139 "gram.y"
+#line 3136 "gram.y"
 {	yyval.node = yyvsp[0].node;  ;
     break;}
 case 589:
-#line 3141 "gram.y"
+#line 3138 "gram.y"
 {	yyval.node = yyvsp[0].node;  ;
     break;}
 case 590:
-#line 3143 "gram.y"
+#line 3140 "gram.y"
 {
 					/* could be a column name or a relation_name */
 					Ident *n = makeNode(Ident);
@@ -7634,51 +7631,51 @@ case 590:
 				;
     break;}
 case 591:
-#line 3151 "gram.y"
+#line 3148 "gram.y"
 {	yyval.node = makeA_Expr(OP, "-", NULL, yyvsp[0].node); ;
     break;}
 case 592:
-#line 3153 "gram.y"
+#line 3150 "gram.y"
 {	yyval.node = makeA_Expr(OP, "+", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 593:
-#line 3155 "gram.y"
+#line 3152 "gram.y"
 {	yyval.node = makeA_Expr(OP, "-", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 594:
-#line 3157 "gram.y"
+#line 3154 "gram.y"
 {	yyval.node = makeA_Expr(OP, "/", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 595:
-#line 3159 "gram.y"
+#line 3156 "gram.y"
 {	yyval.node = makeA_Expr(OP, "*", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 596:
-#line 3161 "gram.y"
+#line 3158 "gram.y"
 {	yyval.node = makeA_Expr(OP, "<", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 597:
-#line 3163 "gram.y"
+#line 3160 "gram.y"
 {	yyval.node = makeA_Expr(OP, ">", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 598:
-#line 3165 "gram.y"
+#line 3162 "gram.y"
 {	yyval.node = makeA_Expr(OP, "=", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 599:
-#line 3167 "gram.y"
+#line 3164 "gram.y"
 {	yyval.node = makeA_Expr(OP, ":", NULL, yyvsp[0].node); ;
     break;}
 case 600:
-#line 3169 "gram.y"
+#line 3166 "gram.y"
 {	yyval.node = makeA_Expr(OP, ";", NULL, yyvsp[0].node); ;
     break;}
 case 601:
-#line 3171 "gram.y"
+#line 3168 "gram.y"
 {	yyval.node = makeA_Expr(OP, "|", NULL, yyvsp[0].node); ;
     break;}
 case 602:
-#line 3173 "gram.y"
+#line 3170 "gram.y"
 {
 					yyval.node = (Node *)yyvsp[-2].node;
 					/* AexprConst can be either A_Const or ParamNo */
@@ -7696,7 +7693,7 @@ case 602:
 				;
     break;}
 case 603:
-#line 3189 "gram.y"
+#line 3186 "gram.y"
 {
 					yyval.node = (Node *)yyvsp[-3].node;
 					/* AexprConst can be either A_Const or ParamNo */
@@ -7714,31 +7711,31 @@ case 603:
 				;
     break;}
 case 604:
-#line 3205 "gram.y"
+#line 3202 "gram.y"
 {	yyval.node = yyvsp[-1].node; ;
     break;}
 case 605:
-#line 3207 "gram.y"
+#line 3204 "gram.y"
 {	yyval.node = makeIndexable(yyvsp[-1].str,yyvsp[-2].node,yyvsp[0].node);	;
     break;}
 case 606:
-#line 3209 "gram.y"
+#line 3206 "gram.y"
 {	yyval.node = makeIndexable("~~", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 607:
-#line 3211 "gram.y"
+#line 3208 "gram.y"
 {	yyval.node = makeA_Expr(OP, "!~~", yyvsp[-3].node, yyvsp[0].node); ;
     break;}
 case 608:
-#line 3213 "gram.y"
+#line 3210 "gram.y"
 {	yyval.node = makeA_Expr(OP, yyvsp[-1].str, NULL, yyvsp[0].node); ;
     break;}
 case 609:
-#line 3215 "gram.y"
+#line 3212 "gram.y"
 {	yyval.node = makeA_Expr(OP, yyvsp[0].str, yyvsp[-1].node, NULL); ;
     break;}
 case 610:
-#line 3217 "gram.y"
+#line 3214 "gram.y"
 {
 					/* cheap hack for aggregate (eg. count) */
 					FuncCall *n = makeNode(FuncCall);
@@ -7752,7 +7749,7 @@ case 610:
 				;
     break;}
 case 611:
-#line 3229 "gram.y"
+#line 3226 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = yyvsp[-2].str;
@@ -7761,7 +7758,7 @@ case 611:
 				;
     break;}
 case 612:
-#line 3236 "gram.y"
+#line 3233 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = yyvsp[-3].str;
@@ -7770,7 +7767,7 @@ case 612:
 				;
     break;}
 case 613:
-#line 3243 "gram.y"
+#line 3240 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					TypeName *t = makeNode(TypeName);
@@ -7787,7 +7784,7 @@ case 613:
 				;
     break;}
 case 614:
-#line 3258 "gram.y"
+#line 3255 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					TypeName *t = makeNode(TypeName);
@@ -7804,7 +7801,7 @@ case 614:
 				;
     break;}
 case 615:
-#line 3273 "gram.y"
+#line 3270 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					A_Const *s = makeNode(A_Const);
@@ -7828,7 +7825,7 @@ case 615:
 				;
     break;}
 case 616:
-#line 3295 "gram.y"
+#line 3292 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					TypeName *t = makeNode(TypeName);
@@ -7845,7 +7842,7 @@ case 616:
 				;
     break;}
 case 617:
-#line 3310 "gram.y"
+#line 3307 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					A_Const *s = makeNode(A_Const);
@@ -7869,7 +7866,7 @@ case 617:
 				;
     break;}
 case 618:
-#line 3332 "gram.y"
+#line 3329 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "getpgusername";
@@ -7878,7 +7875,7 @@ case 618:
 				;
     break;}
 case 619:
-#line 3339 "gram.y"
+#line 3336 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "getpgusername";
@@ -7887,7 +7884,7 @@ case 619:
 				;
     break;}
 case 620:
-#line 3346 "gram.y"
+#line 3343 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = NIL;
@@ -7899,7 +7896,7 @@ case 620:
 				;
     break;}
 case 621:
-#line 3356 "gram.y"
+#line 3353 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "date_part";
@@ -7908,7 +7905,7 @@ case 621:
 				;
     break;}
 case 622:
-#line 3363 "gram.y"
+#line 3360 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "strpos";
@@ -7917,7 +7914,7 @@ case 622:
 				;
     break;}
 case 623:
-#line 3370 "gram.y"
+#line 3367 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "substr";
@@ -7926,7 +7923,7 @@ case 623:
 				;
     break;}
 case 624:
-#line 3378 "gram.y"
+#line 3375 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "btrim";
@@ -7935,7 +7932,7 @@ case 624:
 				;
     break;}
 case 625:
-#line 3385 "gram.y"
+#line 3382 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "ltrim";
@@ -7944,7 +7941,7 @@ case 625:
 				;
     break;}
 case 626:
-#line 3392 "gram.y"
+#line 3389 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "rtrim";
@@ -7953,7 +7950,7 @@ case 626:
 				;
     break;}
 case 627:
-#line 3399 "gram.y"
+#line 3396 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "btrim";
@@ -7962,23 +7959,23 @@ case 627:
 				;
     break;}
 case 628:
-#line 3406 "gram.y"
+#line 3403 "gram.y"
 {	yyval.node = makeA_Expr(ISNULL, NULL, yyvsp[-1].node, NULL); ;
     break;}
 case 629:
-#line 3408 "gram.y"
+#line 3405 "gram.y"
 {	yyval.node = makeA_Expr(ISNULL, NULL, yyvsp[-2].node, NULL); ;
     break;}
 case 630:
-#line 3410 "gram.y"
+#line 3407 "gram.y"
 {	yyval.node = makeA_Expr(NOTNULL, NULL, yyvsp[-1].node, NULL); ;
     break;}
 case 631:
-#line 3412 "gram.y"
+#line 3409 "gram.y"
 {	yyval.node = makeA_Expr(NOTNULL, NULL, yyvsp[-3].node, NULL); ;
     break;}
 case 632:
-#line 3419 "gram.y"
+#line 3416 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					n->val.type = T_String;
@@ -7990,7 +7987,7 @@ case 632:
 				;
     break;}
 case 633:
-#line 3429 "gram.y"
+#line 3426 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					n->val.type = T_String;
@@ -8002,7 +7999,7 @@ case 633:
 				;
     break;}
 case 634:
-#line 3439 "gram.y"
+#line 3436 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					n->val.type = T_String;
@@ -8014,7 +8011,7 @@ case 634:
 				;
     break;}
 case 635:
-#line 3449 "gram.y"
+#line 3446 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					n->val.type = T_String;
@@ -8026,7 +8023,7 @@ case 635:
 				;
     break;}
 case 636:
-#line 3459 "gram.y"
+#line 3456 "gram.y"
 {
 					yyval.node = makeA_Expr(AND, NULL,
 						makeA_Expr(OP, ">=", yyvsp[-4].node, yyvsp[-2].node),
@@ -8034,7 +8031,7 @@ case 636:
 				;
     break;}
 case 637:
-#line 3465 "gram.y"
+#line 3462 "gram.y"
 {
 					yyval.node = makeA_Expr(OR, NULL,
 						makeA_Expr(OP, "<", yyvsp[-5].node, yyvsp[-2].node),
@@ -8042,11 +8039,11 @@ case 637:
 				;
     break;}
 case 638:
-#line 3470 "gram.y"
+#line 3467 "gram.y"
 { saved_In_Expr = lcons(yyvsp[-1].node,saved_In_Expr); ;
     break;}
 case 639:
-#line 3471 "gram.y"
+#line 3468 "gram.y"
 {
 					saved_In_Expr = lnext(saved_In_Expr);
 					if (nodeTag(yyvsp[-1].node) == T_SubLink)
@@ -8062,11 +8059,11 @@ case 639:
 				;
     break;}
 case 640:
-#line 3484 "gram.y"
+#line 3481 "gram.y"
 { saved_In_Expr = lcons(yyvsp[-2].node,saved_In_Expr); ;
     break;}
 case 641:
-#line 3485 "gram.y"
+#line 3482 "gram.y"
 {
 					saved_In_Expr = lnext(saved_In_Expr);
 					if (nodeTag(yyvsp[-1].node) == T_SubLink)
@@ -8082,7 +8079,7 @@ case 641:
 				;
     break;}
 case 642:
-#line 3499 "gram.y"
+#line 3496 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-4].node, NULL);
@@ -8094,7 +8091,7 @@ case 642:
 				;
     break;}
 case 643:
-#line 3509 "gram.y"
+#line 3506 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-4].node, NULL);
@@ -8106,7 +8103,7 @@ case 643:
 				;
     break;}
 case 644:
-#line 3519 "gram.y"
+#line 3516 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-4].node, NULL);
@@ -8118,7 +8115,7 @@ case 644:
 				;
     break;}
 case 645:
-#line 3529 "gram.y"
+#line 3526 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-4].node, NULL);
@@ -8130,7 +8127,7 @@ case 645:
 				;
     break;}
 case 646:
-#line 3539 "gram.y"
+#line 3536 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-4].node, NULL);
@@ -8142,7 +8139,7 @@ case 646:
 				;
     break;}
 case 647:
-#line 3549 "gram.y"
+#line 3546 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-4].node, NULL);
@@ -8154,7 +8151,7 @@ case 647:
 				;
     break;}
 case 648:
-#line 3559 "gram.y"
+#line 3556 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-4].node, NULL);
@@ -8166,7 +8163,7 @@ case 648:
 				;
     break;}
 case 649:
-#line 3569 "gram.y"
+#line 3566 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-4].node, NULL);
@@ -8178,7 +8175,7 @@ case 649:
 				;
     break;}
 case 650:
-#line 3579 "gram.y"
+#line 3576 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node,NIL);
@@ -8190,7 +8187,7 @@ case 650:
 				;
     break;}
 case 651:
-#line 3589 "gram.y"
+#line 3586 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node,NIL);
@@ -8202,7 +8199,7 @@ case 651:
 				;
     break;}
 case 652:
-#line 3599 "gram.y"
+#line 3596 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node,NIL);
@@ -8214,7 +8211,7 @@ case 652:
 				;
     break;}
 case 653:
-#line 3609 "gram.y"
+#line 3606 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node,NIL);
@@ -8226,7 +8223,7 @@ case 653:
 				;
     break;}
 case 654:
-#line 3619 "gram.y"
+#line 3616 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node,NIL);
@@ -8238,7 +8235,7 @@ case 654:
 				;
     break;}
 case 655:
-#line 3629 "gram.y"
+#line 3626 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node,NIL);
@@ -8250,7 +8247,7 @@ case 655:
 				;
     break;}
 case 656:
-#line 3639 "gram.y"
+#line 3636 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node,NIL);
@@ -8262,7 +8259,7 @@ case 656:
 				;
     break;}
 case 657:
-#line 3649 "gram.y"
+#line 3646 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node,NIL);
@@ -8274,7 +8271,7 @@ case 657:
 				;
     break;}
 case 658:
-#line 3659 "gram.y"
+#line 3656 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node, NULL);
@@ -8286,7 +8283,7 @@ case 658:
 				;
     break;}
 case 659:
-#line 3669 "gram.y"
+#line 3666 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node, NULL);
@@ -8298,7 +8295,7 @@ case 659:
 				;
     break;}
 case 660:
-#line 3679 "gram.y"
+#line 3676 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node, NULL);
@@ -8310,7 +8307,7 @@ case 660:
 				;
     break;}
 case 661:
-#line 3689 "gram.y"
+#line 3686 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node, NULL);
@@ -8322,7 +8319,7 @@ case 661:
 				;
     break;}
 case 662:
-#line 3699 "gram.y"
+#line 3696 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node, NULL);
@@ -8334,7 +8331,7 @@ case 662:
 				;
     break;}
 case 663:
-#line 3709 "gram.y"
+#line 3706 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node, NULL);
@@ -8346,7 +8343,7 @@ case 663:
 				;
     break;}
 case 664:
-#line 3719 "gram.y"
+#line 3716 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node, NULL);
@@ -8358,7 +8355,7 @@ case 664:
 				;
     break;}
 case 665:
-#line 3729 "gram.y"
+#line 3726 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->lefthand = lcons(yyvsp[-5].node, NULL);
@@ -8370,30 +8367,30 @@ case 665:
 				;
     break;}
 case 666:
-#line 3739 "gram.y"
+#line 3736 "gram.y"
 {	yyval.node = makeA_Expr(AND, NULL, yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 667:
-#line 3741 "gram.y"
+#line 3738 "gram.y"
 {	yyval.node = makeA_Expr(OR, NULL, yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 668:
-#line 3743 "gram.y"
+#line 3740 "gram.y"
 {	yyval.node = makeA_Expr(NOT, NULL, NULL, yyvsp[0].node); ;
     break;}
 case 669:
-#line 3753 "gram.y"
+#line 3750 "gram.y"
 {
 					yyvsp[-1].attr->indirection = yyvsp[0].list;
 					yyval.node = (Node *)yyvsp[-1].attr;
 				;
     break;}
 case 670:
-#line 3758 "gram.y"
+#line 3755 "gram.y"
 {	yyval.node = yyvsp[0].node;  ;
     break;}
 case 671:
-#line 3760 "gram.y"
+#line 3757 "gram.y"
 {
 					/* could be a column name or a relation_name */
 					Ident *n = makeNode(Ident);
@@ -8403,39 +8400,39 @@ case 671:
 				;
     break;}
 case 672:
-#line 3768 "gram.y"
+#line 3765 "gram.y"
 {	yyval.node = makeA_Expr(OP, "-", NULL, yyvsp[0].node); ;
     break;}
 case 673:
-#line 3770 "gram.y"
+#line 3767 "gram.y"
 {	yyval.node = makeA_Expr(OP, "+", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 674:
-#line 3772 "gram.y"
+#line 3769 "gram.y"
 {	yyval.node = makeA_Expr(OP, "-", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 675:
-#line 3774 "gram.y"
+#line 3771 "gram.y"
 {	yyval.node = makeA_Expr(OP, "/", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 676:
-#line 3776 "gram.y"
+#line 3773 "gram.y"
 {	yyval.node = makeA_Expr(OP, "*", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 677:
-#line 3778 "gram.y"
+#line 3775 "gram.y"
 {	yyval.node = makeA_Expr(OP, ":", NULL, yyvsp[0].node); ;
     break;}
 case 678:
-#line 3780 "gram.y"
+#line 3777 "gram.y"
 {	yyval.node = makeA_Expr(OP, ";", NULL, yyvsp[0].node); ;
     break;}
 case 679:
-#line 3782 "gram.y"
+#line 3779 "gram.y"
 {	yyval.node = makeA_Expr(OP, "|", NULL, yyvsp[0].node); ;
     break;}
 case 680:
-#line 3784 "gram.y"
+#line 3781 "gram.y"
 {
 					yyval.node = (Node *)yyvsp[-2].node;
 					/* AexprConst can be either A_Const or ParamNo */
@@ -8453,7 +8450,7 @@ case 680:
 				;
     break;}
 case 681:
-#line 3800 "gram.y"
+#line 3797 "gram.y"
 {
 					yyval.node = (Node *)yyvsp[-3].node;
 					/* AexprConst can be either A_Const or ParamNo */
@@ -8471,23 +8468,23 @@ case 681:
 				;
     break;}
 case 682:
-#line 3816 "gram.y"
+#line 3813 "gram.y"
 {	yyval.node = yyvsp[-1].node; ;
     break;}
 case 683:
-#line 3818 "gram.y"
+#line 3815 "gram.y"
 {	yyval.node = makeIndexable(yyvsp[-1].str,yyvsp[-2].node,yyvsp[0].node);	;
     break;}
 case 684:
-#line 3820 "gram.y"
+#line 3817 "gram.y"
 {	yyval.node = makeA_Expr(OP, yyvsp[-1].str, NULL, yyvsp[0].node); ;
     break;}
 case 685:
-#line 3822 "gram.y"
+#line 3819 "gram.y"
 {	yyval.node = makeA_Expr(OP, yyvsp[0].str, yyvsp[-1].node, NULL); ;
     break;}
 case 686:
-#line 3824 "gram.y"
+#line 3821 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = yyvsp[-2].str;
@@ -8496,7 +8493,7 @@ case 686:
 				;
     break;}
 case 687:
-#line 3831 "gram.y"
+#line 3828 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = yyvsp[-3].str;
@@ -8505,7 +8502,7 @@ case 687:
 				;
     break;}
 case 688:
-#line 3838 "gram.y"
+#line 3835 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					TypeName *t = makeNode(TypeName);
@@ -8522,7 +8519,7 @@ case 688:
 				;
     break;}
 case 689:
-#line 3853 "gram.y"
+#line 3850 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					TypeName *t = makeNode(TypeName);
@@ -8539,7 +8536,7 @@ case 689:
 				;
     break;}
 case 690:
-#line 3868 "gram.y"
+#line 3865 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					A_Const *s = makeNode(A_Const);
@@ -8563,7 +8560,7 @@ case 690:
 				;
     break;}
 case 691:
-#line 3890 "gram.y"
+#line 3887 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					TypeName *t = makeNode(TypeName);
@@ -8580,7 +8577,7 @@ case 691:
 				;
     break;}
 case 692:
-#line 3905 "gram.y"
+#line 3902 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					A_Const *s = makeNode(A_Const);
@@ -8604,7 +8601,7 @@ case 692:
 				;
     break;}
 case 693:
-#line 3927 "gram.y"
+#line 3924 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "getpgusername";
@@ -8613,7 +8610,7 @@ case 693:
 				;
     break;}
 case 694:
-#line 3934 "gram.y"
+#line 3931 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "getpgusername";
@@ -8622,7 +8619,7 @@ case 694:
 				;
     break;}
 case 695:
-#line 3941 "gram.y"
+#line 3938 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "strpos";
@@ -8631,7 +8628,7 @@ case 695:
 				;
     break;}
 case 696:
-#line 3948 "gram.y"
+#line 3945 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "substr";
@@ -8640,7 +8637,7 @@ case 696:
 				;
     break;}
 case 697:
-#line 3956 "gram.y"
+#line 3953 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "btrim";
@@ -8649,7 +8646,7 @@ case 697:
 				;
     break;}
 case 698:
-#line 3963 "gram.y"
+#line 3960 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "ltrim";
@@ -8658,7 +8655,7 @@ case 698:
 				;
     break;}
 case 699:
-#line 3970 "gram.y"
+#line 3967 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "rtrim";
@@ -8667,7 +8664,7 @@ case 699:
 				;
     break;}
 case 700:
-#line 3977 "gram.y"
+#line 3974 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "btrim";
@@ -8676,7 +8673,7 @@ case 700:
 				;
     break;}
 case 701:
-#line 3986 "gram.y"
+#line 3983 "gram.y"
 {
 					A_Indices *ai = makeNode(A_Indices);
 					ai->lidx = NULL;
@@ -8685,7 +8682,7 @@ case 701:
 				;
     break;}
 case 702:
-#line 3993 "gram.y"
+#line 3990 "gram.y"
 {
 					A_Indices *ai = makeNode(A_Indices);
 					ai->lidx = yyvsp[-4].node;
@@ -8694,23 +8691,23 @@ case 702:
 				;
     break;}
 case 703:
-#line 4000 "gram.y"
+#line 3997 "gram.y"
 {	yyval.list = NIL; ;
     break;}
 case 704:
-#line 4004 "gram.y"
+#line 4001 "gram.y"
 { yyval.list = lcons(yyvsp[0].node, NIL); ;
     break;}
 case 705:
-#line 4006 "gram.y"
+#line 4003 "gram.y"
 { yyval.list = lappend(yyvsp[-2].list, yyvsp[0].node); ;
     break;}
 case 706:
-#line 4008 "gram.y"
+#line 4005 "gram.y"
 { yyval.list = lappend(yyvsp[-2].list, yyvsp[0].node); ;
     break;}
 case 707:
-#line 4012 "gram.y"
+#line 4009 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					n->val.type = T_String;
@@ -8719,66 +8716,66 @@ case 707:
 				;
     break;}
 case 708:
-#line 4019 "gram.y"
+#line 4016 "gram.y"
 {	yyval.list = NIL; ;
     break;}
 case 709:
-#line 4022 "gram.y"
+#line 4019 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 710:
-#line 4023 "gram.y"
+#line 4020 "gram.y"
 { yyval.str = "tz_hour"; ;
     break;}
 case 711:
-#line 4024 "gram.y"
+#line 4021 "gram.y"
 { yyval.str = "tz_minute"; ;
     break;}
 case 712:
-#line 4028 "gram.y"
+#line 4025 "gram.y"
 {	yyval.list = makeList(yyvsp[0].node, yyvsp[-2].node, -1); ;
     break;}
 case 713:
-#line 4030 "gram.y"
+#line 4027 "gram.y"
 {	yyval.list = NIL; ;
     break;}
 case 714:
-#line 4034 "gram.y"
+#line 4031 "gram.y"
 {
 					yyvsp[-1].attr->indirection = yyvsp[0].list;
 					yyval.node = (Node *)yyvsp[-1].attr;
 				;
     break;}
 case 715:
-#line 4039 "gram.y"
+#line 4036 "gram.y"
 {	yyval.node = yyvsp[0].node;  ;
     break;}
 case 716:
-#line 4041 "gram.y"
+#line 4038 "gram.y"
 {	yyval.node = makeA_Expr(OP, "-", NULL, yyvsp[0].node); ;
     break;}
 case 717:
-#line 4043 "gram.y"
+#line 4040 "gram.y"
 {	yyval.node = makeA_Expr(OP, "+", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 718:
-#line 4045 "gram.y"
+#line 4042 "gram.y"
 {	yyval.node = makeA_Expr(OP, "-", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 719:
-#line 4047 "gram.y"
+#line 4044 "gram.y"
 {	yyval.node = makeA_Expr(OP, "/", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 720:
-#line 4049 "gram.y"
+#line 4046 "gram.y"
 {	yyval.node = makeA_Expr(OP, "*", yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 721:
-#line 4051 "gram.y"
+#line 4048 "gram.y"
 {	yyval.node = makeA_Expr(OP, "|", NULL, yyvsp[0].node); ;
     break;}
 case 722:
-#line 4053 "gram.y"
+#line 4050 "gram.y"
 {
 					yyval.node = (Node *)yyvsp[-2].node;
 					/* AexprConst can be either A_Const or ParamNo */
@@ -8796,7 +8793,7 @@ case 722:
 				;
     break;}
 case 723:
-#line 4069 "gram.y"
+#line 4066 "gram.y"
 {
 					yyval.node = (Node *)yyvsp[-3].node;
 					/* AexprConst can be either A_Const or ParamNo */
@@ -8814,23 +8811,23 @@ case 723:
 				;
     break;}
 case 724:
-#line 4085 "gram.y"
+#line 4082 "gram.y"
 {	yyval.node = yyvsp[-1].node; ;
     break;}
 case 725:
-#line 4087 "gram.y"
+#line 4084 "gram.y"
 {	yyval.node = makeA_Expr(OP, yyvsp[-1].str, yyvsp[-2].node, yyvsp[0].node); ;
     break;}
 case 726:
-#line 4089 "gram.y"
+#line 4086 "gram.y"
 {	yyval.node = makeA_Expr(OP, yyvsp[-1].str, NULL, yyvsp[0].node); ;
     break;}
 case 727:
-#line 4091 "gram.y"
+#line 4088 "gram.y"
 {	yyval.node = makeA_Expr(OP, yyvsp[0].str, yyvsp[-1].node, NULL); ;
     break;}
 case 728:
-#line 4093 "gram.y"
+#line 4090 "gram.y"
 {
 					/* could be a column name or a relation_name */
 					Ident *n = makeNode(Ident);
@@ -8840,7 +8837,7 @@ case 728:
 				;
     break;}
 case 729:
-#line 4101 "gram.y"
+#line 4098 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = yyvsp[-2].str;
@@ -8849,7 +8846,7 @@ case 729:
 				;
     break;}
 case 730:
-#line 4108 "gram.y"
+#line 4105 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = yyvsp[-3].str;
@@ -8858,7 +8855,7 @@ case 730:
 				;
     break;}
 case 731:
-#line 4115 "gram.y"
+#line 4112 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "strpos";
@@ -8867,7 +8864,7 @@ case 731:
 				;
     break;}
 case 732:
-#line 4122 "gram.y"
+#line 4119 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "substr";
@@ -8876,7 +8873,7 @@ case 732:
 				;
     break;}
 case 733:
-#line 4130 "gram.y"
+#line 4127 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "btrim";
@@ -8885,7 +8882,7 @@ case 733:
 				;
     break;}
 case 734:
-#line 4137 "gram.y"
+#line 4134 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "ltrim";
@@ -8894,7 +8891,7 @@ case 734:
 				;
     break;}
 case 735:
-#line 4144 "gram.y"
+#line 4141 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "rtrim";
@@ -8903,7 +8900,7 @@ case 735:
 				;
     break;}
 case 736:
-#line 4151 "gram.y"
+#line 4148 "gram.y"
 {
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = "btrim";
@@ -8912,21 +8909,21 @@ case 736:
 				;
     break;}
 case 737:
-#line 4160 "gram.y"
+#line 4157 "gram.y"
 {
 					yyval.list = nconc(nconc(yyvsp[-2].list,yyvsp[-1].list),yyvsp[0].list);
 				;
     break;}
 case 738:
-#line 4164 "gram.y"
+#line 4161 "gram.y"
 {	yyval.list = NIL; ;
     break;}
 case 739:
-#line 4168 "gram.y"
+#line 4165 "gram.y"
 {	yyval.list = yyvsp[0].list; ;
     break;}
 case 740:
-#line 4170 "gram.y"
+#line 4167 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					n->val.type = T_Integer;
@@ -8935,27 +8932,27 @@ case 740:
 				;
     break;}
 case 741:
-#line 4179 "gram.y"
+#line 4176 "gram.y"
 {	yyval.list = yyvsp[0].list; ;
     break;}
 case 742:
-#line 4181 "gram.y"
+#line 4178 "gram.y"
 {	yyval.list = NIL; ;
     break;}
 case 743:
-#line 4185 "gram.y"
+#line 4182 "gram.y"
 { yyval.list = lappend(yyvsp[0].list, yyvsp[-2].node); ;
     break;}
 case 744:
-#line 4187 "gram.y"
+#line 4184 "gram.y"
 { yyval.list = yyvsp[0].list; ;
     break;}
 case 745:
-#line 4189 "gram.y"
+#line 4186 "gram.y"
 { yyval.list = yyvsp[0].list; ;
     break;}
 case 746:
-#line 4193 "gram.y"
+#line 4190 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->subselect = yyvsp[0].node;
@@ -8963,21 +8960,21 @@ case 746:
 				;
     break;}
 case 747:
-#line 4199 "gram.y"
+#line 4196 "gram.y"
 {	yyval.node = yyvsp[0].node; ;
     break;}
 case 748:
-#line 4203 "gram.y"
+#line 4200 "gram.y"
 {	yyval.node = makeA_Expr(OP, "=", lfirst(saved_In_Expr), yyvsp[0].node); ;
     break;}
 case 749:
-#line 4205 "gram.y"
+#line 4202 "gram.y"
 {	yyval.node = makeA_Expr(OR, NULL, yyvsp[-2].node,
 						makeA_Expr(OP, "=", lfirst(saved_In_Expr), yyvsp[0].node));
 				;
     break;}
 case 750:
-#line 4211 "gram.y"
+#line 4208 "gram.y"
 {
 					SubLink *n = makeNode(SubLink);
 					n->subselect = yyvsp[0].node;
@@ -8985,21 +8982,21 @@ case 750:
 				;
     break;}
 case 751:
-#line 4217 "gram.y"
+#line 4214 "gram.y"
 {	yyval.node = yyvsp[0].node; ;
     break;}
 case 752:
-#line 4221 "gram.y"
+#line 4218 "gram.y"
 {	yyval.node = makeA_Expr(OP, "<>", lfirst(saved_In_Expr), yyvsp[0].node); ;
     break;}
 case 753:
-#line 4223 "gram.y"
+#line 4220 "gram.y"
 {	yyval.node = makeA_Expr(AND, NULL, yyvsp[-2].node,
 						makeA_Expr(OP, "<>", lfirst(saved_In_Expr), yyvsp[0].node));
 				;
     break;}
 case 754:
-#line 4229 "gram.y"
+#line 4226 "gram.y"
 {
 					yyval.attr = makeNode(Attr);
 					yyval.attr->relname = yyvsp[-2].str;
@@ -9009,7 +9006,7 @@ case 754:
 				;
     break;}
 case 755:
-#line 4237 "gram.y"
+#line 4234 "gram.y"
 {
 					yyval.attr = makeNode(Attr);
 					yyval.attr->relname = NULL;
@@ -9019,27 +9016,27 @@ case 755:
 				;
     break;}
 case 756:
-#line 4247 "gram.y"
+#line 4244 "gram.y"
 { yyval.list = lcons(makeString(yyvsp[0].str), NIL); ;
     break;}
 case 757:
-#line 4249 "gram.y"
+#line 4246 "gram.y"
 { yyval.list = lappend(yyvsp[-2].list, makeString(yyvsp[0].str)); ;
     break;}
 case 758:
-#line 4251 "gram.y"
+#line 4248 "gram.y"
 { yyval.list = lappend(yyvsp[-2].list, makeString("*")); ;
     break;}
 case 759:
-#line 4262 "gram.y"
+#line 4259 "gram.y"
 {	yyval.list = lappend(yyvsp[-2].list,yyvsp[0].target);  ;
     break;}
 case 760:
-#line 4264 "gram.y"
+#line 4261 "gram.y"
 {	yyval.list = lcons(yyvsp[0].target, NIL);  ;
     break;}
 case 761:
-#line 4266 "gram.y"
+#line 4263 "gram.y"
 {
 					ResTarget *rt = makeNode(ResTarget);
 					Attr *att = makeNode(Attr);
@@ -9054,7 +9051,7 @@ case 761:
 				;
     break;}
 case 762:
-#line 4281 "gram.y"
+#line 4278 "gram.y"
 {
 					yyval.target = makeNode(ResTarget);
 					yyval.target->name = yyvsp[-3].str;
@@ -9063,7 +9060,7 @@ case 762:
 				;
     break;}
 case 763:
-#line 4288 "gram.y"
+#line 4285 "gram.y"
 {
 					yyval.target = makeNode(ResTarget);
 					yyval.target->name = NULL;
@@ -9072,7 +9069,7 @@ case 763:
 				;
     break;}
 case 764:
-#line 4295 "gram.y"
+#line 4292 "gram.y"
 {
 					Attr *att = makeNode(Attr);
 					att->relname = yyvsp[-2].str;
@@ -9086,15 +9083,15 @@ case 764:
 				;
     break;}
 case 765:
-#line 4314 "gram.y"
+#line 4311 "gram.y"
 {	yyval.list = lappend(yyvsp[-2].list, yyvsp[0].target);  ;
     break;}
 case 766:
-#line 4316 "gram.y"
+#line 4313 "gram.y"
 {	yyval.list = lcons(yyvsp[0].target, NIL);  ;
     break;}
 case 767:
-#line 4321 "gram.y"
+#line 4318 "gram.y"
 {
 					yyval.target = makeNode(ResTarget);
 					yyval.target->name = yyvsp[0].str;
@@ -9103,7 +9100,7 @@ case 767:
 				;
     break;}
 case 768:
-#line 4328 "gram.y"
+#line 4325 "gram.y"
 {
 					yyval.target = makeNode(ResTarget);
 					yyval.target->name = NULL;
@@ -9112,7 +9109,7 @@ case 768:
 				;
     break;}
 case 769:
-#line 4335 "gram.y"
+#line 4332 "gram.y"
 {
 					Attr *att = makeNode(Attr);
 					att->relname = yyvsp[-2].str;
@@ -9126,7 +9123,7 @@ case 769:
 				;
     break;}
 case 770:
-#line 4347 "gram.y"
+#line 4344 "gram.y"
 {
 					Attr *att = makeNode(Attr);
 					att->relname = "*";
@@ -9140,22 +9137,22 @@ case 770:
 				;
     break;}
 case 771:
-#line 4360 "gram.y"
+#line 4357 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 772:
-#line 4361 "gram.y"
+#line 4358 "gram.y"
 { yyval.str = NULL; ;
     break;}
 case 773:
-#line 4365 "gram.y"
+#line 4362 "gram.y"
 {
 					yyval.str = yyvsp[0].str;
 					StrNCpy(saved_relname, yyvsp[0].str, NAMEDATALEN);
 				;
     break;}
 case 774:
-#line 4370 "gram.y"
+#line 4367 "gram.y"
 {
 					/* disallow refs to variable system tables */
 					if (strcmp(LogRelationName, yyvsp[0].str) == 0
@@ -9167,43 +9164,43 @@ case 774:
 				;
     break;}
 case 775:
-#line 4381 "gram.y"
+#line 4378 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 776:
-#line 4382 "gram.y"
+#line 4379 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 777:
-#line 4383 "gram.y"
+#line 4380 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 778:
-#line 4384 "gram.y"
+#line 4381 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 779:
-#line 4385 "gram.y"
+#line 4382 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 780:
-#line 4391 "gram.y"
+#line 4388 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 781:
-#line 4392 "gram.y"
+#line 4389 "gram.y"
 { yyval.str = xlateSqlFunc(yyvsp[0].str); ;
     break;}
 case 782:
-#line 4394 "gram.y"
+#line 4391 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 783:
-#line 4395 "gram.y"
+#line 4392 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 784:
-#line 4401 "gram.y"
+#line 4398 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					n->val.type = T_Integer;
@@ -9212,7 +9209,7 @@ case 784:
 				;
     break;}
 case 785:
-#line 4408 "gram.y"
+#line 4405 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					n->val.type = T_Float;
@@ -9221,7 +9218,7 @@ case 785:
 				;
     break;}
 case 786:
-#line 4415 "gram.y"
+#line 4412 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					n->val.type = T_String;
@@ -9230,7 +9227,7 @@ case 786:
 				;
     break;}
 case 787:
-#line 4422 "gram.y"
+#line 4419 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					n->typename = yyvsp[-1].typnam;
@@ -9240,11 +9237,11 @@ case 787:
 				;
     break;}
 case 788:
-#line 4430 "gram.y"
+#line 4427 "gram.y"
 {	yyval.node = (Node *)yyvsp[0].paramno;  ;
     break;}
 case 789:
-#line 4432 "gram.y"
+#line 4429 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					n->val.type = T_String;
@@ -9256,7 +9253,7 @@ case 789:
 				;
     break;}
 case 790:
-#line 4442 "gram.y"
+#line 4439 "gram.y"
 {
 					A_Const *n = makeNode(A_Const);
 					n->val.type = T_String;
@@ -9268,234 +9265,234 @@ case 790:
 				;
     break;}
 case 791:
-#line 4454 "gram.y"
+#line 4451 "gram.y"
 {
 					yyval.paramno = makeNode(ParamNo);
 					yyval.paramno->number = yyvsp[0].ival;
 				;
     break;}
 case 792:
-#line 4460 "gram.y"
+#line 4457 "gram.y"
 { yyval.ival = yyvsp[0].ival; ;
     break;}
 case 793:
-#line 4461 "gram.y"
+#line 4458 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 794:
-#line 4462 "gram.y"
+#line 4459 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 795:
-#line 4470 "gram.y"
+#line 4467 "gram.y"
 {	yyval.str = xlateSqlType(yyvsp[0].str); ;
     break;}
 case 796:
-#line 4472 "gram.y"
+#line 4469 "gram.y"
 {	yyval.str = xlateSqlType(yyvsp[0].str); ;
     break;}
 case 797:
-#line 4474 "gram.y"
+#line 4471 "gram.y"
 {	yyval.str = xlateSqlType(yyvsp[0].str); ;
     break;}
 case 798:
-#line 4484 "gram.y"
+#line 4481 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 799:
-#line 4485 "gram.y"
+#line 4482 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 800:
-#line 4486 "gram.y"
+#line 4483 "gram.y"
 { yyval.str = "action"; ;
     break;}
 case 801:
-#line 4487 "gram.y"
+#line 4484 "gram.y"
 { yyval.str = "cache"; ;
     break;}
 case 802:
-#line 4488 "gram.y"
+#line 4485 "gram.y"
 { yyval.str = "cycle"; ;
     break;}
 case 803:
-#line 4489 "gram.y"
+#line 4486 "gram.y"
 { yyval.str = "database"; ;
     break;}
 case 804:
-#line 4490 "gram.y"
+#line 4487 "gram.y"
 { yyval.str = "delimiters"; ;
     break;}
 case 805:
-#line 4491 "gram.y"
+#line 4488 "gram.y"
 { yyval.str = "double"; ;
     break;}
 case 806:
-#line 4492 "gram.y"
+#line 4489 "gram.y"
 { yyval.str = "each"; ;
     break;}
 case 807:
-#line 4493 "gram.y"
+#line 4490 "gram.y"
 { yyval.str = "function"; ;
     break;}
 case 808:
-#line 4494 "gram.y"
+#line 4491 "gram.y"
 { yyval.str = "increment"; ;
     break;}
 case 809:
-#line 4495 "gram.y"
+#line 4492 "gram.y"
 { yyval.str = "index"; ;
     break;}
 case 810:
-#line 4496 "gram.y"
+#line 4493 "gram.y"
 { yyval.str = "key"; ;
     break;}
 case 811:
-#line 4497 "gram.y"
+#line 4494 "gram.y"
 { yyval.str = "language"; ;
     break;}
 case 812:
-#line 4498 "gram.y"
+#line 4495 "gram.y"
 { yyval.str = "location"; ;
     break;}
 case 813:
-#line 4499 "gram.y"
+#line 4496 "gram.y"
 { yyval.str = "match"; ;
     break;}
 case 814:
-#line 4500 "gram.y"
+#line 4497 "gram.y"
 { yyval.str = "maxvalue"; ;
     break;}
 case 815:
-#line 4501 "gram.y"
+#line 4498 "gram.y"
 { yyval.str = "minvalue"; ;
     break;}
 case 816:
-#line 4502 "gram.y"
+#line 4499 "gram.y"
 { yyval.str = "operator"; ;
     break;}
 case 817:
-#line 4503 "gram.y"
+#line 4500 "gram.y"
 { yyval.str = "option"; ;
     break;}
 case 818:
-#line 4504 "gram.y"
+#line 4501 "gram.y"
 { yyval.str = "password"; ;
     break;}
 case 819:
-#line 4505 "gram.y"
+#line 4502 "gram.y"
 { yyval.str = "privileges"; ;
     break;}
 case 820:
-#line 4506 "gram.y"
+#line 4503 "gram.y"
 { yyval.str = "recipe"; ;
     break;}
 case 821:
-#line 4507 "gram.y"
+#line 4504 "gram.y"
 { yyval.str = "row"; ;
     break;}
 case 822:
-#line 4508 "gram.y"
+#line 4505 "gram.y"
 { yyval.str = "start"; ;
     break;}
 case 823:
-#line 4509 "gram.y"
+#line 4506 "gram.y"
 { yyval.str = "statement"; ;
     break;}
 case 824:
-#line 4510 "gram.y"
+#line 4507 "gram.y"
 { yyval.str = "time"; ;
     break;}
 case 825:
-#line 4511 "gram.y"
+#line 4508 "gram.y"
 { yyval.str = "timezone_hour"; ;
     break;}
 case 826:
-#line 4512 "gram.y"
+#line 4509 "gram.y"
 { yyval.str = "timezone_minute"; ;
     break;}
 case 827:
-#line 4513 "gram.y"
+#line 4510 "gram.y"
 { yyval.str = "trigger"; ;
     break;}
 case 828:
-#line 4514 "gram.y"
+#line 4511 "gram.y"
 { yyval.str = "type"; ;
     break;}
 case 829:
-#line 4515 "gram.y"
+#line 4512 "gram.y"
 { yyval.str = "valid"; ;
     break;}
 case 830:
-#line 4516 "gram.y"
+#line 4513 "gram.y"
 { yyval.str = "version"; ;
     break;}
 case 831:
-#line 4517 "gram.y"
+#line 4514 "gram.y"
 { yyval.str = "zone"; ;
     break;}
 case 832:
-#line 4530 "gram.y"
+#line 4527 "gram.y"
 { yyval.str = yyvsp[0].str; ;
     break;}
 case 833:
-#line 4531 "gram.y"
+#line 4528 "gram.y"
 { yyval.str = "archive"; ;
     break;}
 case 834:
-#line 4532 "gram.y"
+#line 4529 "gram.y"
 { yyval.str = "cluster"; ;
     break;}
 case 835:
-#line 4533 "gram.y"
+#line 4530 "gram.y"
 { yyval.str = "constraint"; ;
     break;}
 case 836:
-#line 4534 "gram.y"
+#line 4531 "gram.y"
 { yyval.str = "cross"; ;
     break;}
 case 837:
-#line 4535 "gram.y"
+#line 4532 "gram.y"
 { yyval.str = "foreign"; ;
     break;}
 case 838:
-#line 4536 "gram.y"
+#line 4533 "gram.y"
 { yyval.str = "group"; ;
     break;}
 case 839:
-#line 4537 "gram.y"
+#line 4534 "gram.y"
 { yyval.str = "load"; ;
     break;}
 case 840:
-#line 4538 "gram.y"
+#line 4535 "gram.y"
 { yyval.str = "order"; ;
     break;}
 case 841:
-#line 4539 "gram.y"
+#line 4536 "gram.y"
 { yyval.str = "position"; ;
     break;}
 case 842:
-#line 4540 "gram.y"
+#line 4537 "gram.y"
 { yyval.str = "precision"; ;
     break;}
 case 843:
-#line 4541 "gram.y"
+#line 4538 "gram.y"
 { yyval.str = "table"; ;
     break;}
 case 844:
-#line 4542 "gram.y"
+#line 4539 "gram.y"
 { yyval.str = "transaction"; ;
     break;}
 case 845:
-#line 4543 "gram.y"
+#line 4540 "gram.y"
 { yyval.str = "true"; ;
     break;}
 case 846:
-#line 4544 "gram.y"
+#line 4541 "gram.y"
 { yyval.str = "false"; ;
     break;}
 case 847:
-#line 4548 "gram.y"
+#line 4545 "gram.y"
 {
 					if (QueryIsRule)
 						yyval.str = "*CURRENT*";
@@ -9504,7 +9501,7 @@ case 847:
 				;
     break;}
 case 848:
-#line 4555 "gram.y"
+#line 4552 "gram.y"
 {
 					if (QueryIsRule)
 						yyval.str = "*NEW*";
@@ -9710,7 +9707,7 @@ yyerrhandle:
   yystate = yyn;
   goto yynewstate;
 }
-#line 4563 "gram.y"
+#line 4560 "gram.y"
 
 
 static Node *
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index df4acded9aea76711806e13df3914c693268ed57..71d4a204c656d3e9aac7bddb5e8fb022ac3cf6db 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.14 1998/07/15 15:56:36 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.15 1998/07/19 05:49:22 momjian Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -2574,9 +2574,6 @@ groupby:  ColId
 
 having_clause:  HAVING a_expr
 				{
-#if FALSE
-					elog(ERROR,"HAVING clause not yet implemented");
-#endif
 					$$ = $2;
 				}
 		| /*EMPTY*/								{ $$ = NULL; }
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 97c468a93892d96813b569aa169bf730fcc2d4b9..aff40937edbe78254c594dd379f77e1a65b58106 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.16 1998/06/15 19:29:07 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.17 1998/07/19 05:49:24 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -342,23 +342,41 @@ ApplyRetrieveRule(Query *parsetree,
 	OffsetVarNodes(rule_action->qual, rt_length);
 	OffsetVarNodes((Node *) rule_action->targetList, rt_length);
 	OffsetVarNodes(rule_qual, rt_length);
+	
+	OffsetVarNodes((Node *) rule_action->groupClause, rt_length);
+	OffsetVarNodes((Node *) rule_action->havingQual, rt_length);
+
 	ChangeVarNodes(rule_action->qual,
 				   PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
 	ChangeVarNodes((Node *) rule_action->targetList,
 				   PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
 	ChangeVarNodes(rule_qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
+
+	ChangeVarNodes((Node *) rule_action->groupClause,
+				   PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
+	ChangeVarNodes((Node *) rule_action->havingQual,
+				   PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
+
 	if (relation_level)
 	{
-		HandleViewRule(parsetree, rtable, rule_action->targetList, rt_index,
-					   modified);
+	  HandleViewRule(parsetree, rtable, rule_action->targetList, rt_index,
+			 modified);
 	}
 	else
 	{
-		HandleRIRAttributeRule(parsetree, rtable, rule_action->targetList,
-							   rt_index, rule->attrno, modified, &badsql);
+	  HandleRIRAttributeRule(parsetree, rtable, rule_action->targetList,
+				 rt_index, rule->attrno, modified, &badsql);
 	}
-	if (*modified && !badsql)
-		AddQual(parsetree, rule_action->qual);
+	if (*modified && !badsql) {
+	  AddQual(parsetree, rule_action->qual);
+	  /* This will only work if the query made to the view defined by the following
+	   * groupClause groups by the same attributes or does not use group at all! */
+	  if (parsetree->groupClause == NULL)
+	    parsetree->groupClause=rule_action->groupClause;
+	  AddHavingQual(parsetree, rule_action->havingQual);
+	  parsetree->hasAggs = (rule_action->hasAggs || parsetree->hasAggs);
+	  parsetree->hasSubLinks = (rule_action->hasSubLinks ||  parsetree->hasSubLinks);
+	}	
 }
 
 static List *
@@ -680,6 +698,8 @@ List *
 QueryRewrite(Query *parsetree)
 {
 	QueryRewriteSubLink(parsetree->qual);
+	QueryRewriteSubLink(parsetree->havingQual);
+
 	return QueryRewriteOne(parsetree);
 }
 
@@ -730,6 +750,8 @@ QueryRewriteSubLink(Node *node)
 				 * SubLink we don't process it as part of this loop.
 				 */
 				QueryRewriteSubLink((Node *) query->qual);
+				
+				QueryRewriteSubLink((Node *) query->havingQual);
 
 				ret = QueryRewriteOne(query);
 				if (!ret)
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index 0c124a36389ed05040585447a53e30759d4b311b..7606698afdf63214e86f0223e40d9968727c979e 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.14 1998/06/15 19:29:07 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.15 1998/07/19 05:49:24 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -55,6 +55,14 @@ OffsetVarNodes(Node *node, int offset)
 				OffsetVarNodes(agg->target, offset);
 			}
 			break;
+		/* This has to be done to make queries using groupclauses work on views */
+	        case T_GroupClause:
+		        {
+			  GroupClause  *group = (GroupClause *) node;
+			  
+			  OffsetVarNodes((Node *)(group->entry), offset);			  
+			}
+		        break;
 		case T_Expr:
 			{
 				Expr	   *expr = (Expr *) node;
@@ -78,6 +86,22 @@ OffsetVarNodes(Node *node, int offset)
 					OffsetVarNodes(lfirst(l), offset);
 			}
 			break;
+		case T_SubLink:
+			{
+				SubLink    *sublink = (SubLink *) node;
+
+				/* We also have to adapt the variables used in sublink->lefthand
+				 * and sublink->oper */
+				OffsetVarNodes((Node *)(sublink->lefthand), offset);
+
+				/* Make sure the first argument of sublink->oper points to the
+				 * same var as sublink->lefthand does otherwise we will
+				 * run into troubles using aggregates (aggno will not be
+				 * set correctly) */
+				lfirst(((Expr *) lfirst(sublink->oper))->args) = 
+				  lfirst(sublink->lefthand);
+			}
+			break;
 		default:
 			/* ignore the others */
 			break;
@@ -105,6 +129,16 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno, int sublevels_up)
 				ChangeVarNodes(agg->target, old_varno, new_varno, sublevels_up);
 			}
 			break;
+		/* This has to be done to make queries using groupclauses work on views */
+	        case T_GroupClause:
+		        {
+			  GroupClause  *group = (GroupClause *) node;
+			  
+			  ChangeVarNodes((Node *)(group->entry),old_varno, new_varno, 
+					 sublevels_up);
+			}
+		        break;
+
 		case T_Expr:
 			{
 				Expr	   *expr = (Expr *) node;
@@ -122,6 +156,8 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno, int sublevels_up)
 					var->varno = new_varno;
 					var->varnoold = new_varno;
 				}
+				if (var->varlevelsup > 0) OffsetVarNodes((Node *)var,3);
+				
 			}
 			break;
 		case T_List:
@@ -139,6 +175,18 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno, int sublevels_up)
 
 				ChangeVarNodes((Node *) query->qual, old_varno, new_varno,
 							   sublevels_up + 1);
+
+				/* We also have to adapt the variables used in sublink->lefthand
+				 * and sublink->oper */
+				ChangeVarNodes((Node *) (sublink->lefthand), old_varno, new_varno,
+							   sublevels_up);
+				
+				/* Make sure the first argument of sublink->oper points to the
+				 * same var as sublink->lefthand does otherwise we will
+				 * run into troubles using aggregates (aggno will not be
+				 * set correctly */
+				/* lfirst(((Expr *) lfirst(sublink->oper))->args) = 
+				  lfirst(sublink->lefthand); */
 			}
 			break;
 		default:
@@ -165,6 +213,26 @@ AddQual(Query *parsetree, Node *qual)
 			(Node *) make_andclause(makeList(parsetree->qual, copy, -1));
 }
 
+/* Adds the given havingQual to the one already contained in the parsetree just as
+ * AddQual does for the normal 'where' qual */
+void
+AddHavingQual(Query *parsetree, Node *havingQual)
+{
+  Node	   *copy, *old;
+
+	if (havingQual == NULL)
+		return;
+
+	copy = copyObject(havingQual);
+	old = parsetree->havingQual;
+	if (old == NULL)
+		parsetree->havingQual = copy;
+	else
+		parsetree->havingQual =
+			(Node *) make_andclause(makeList(parsetree->havingQual, copy, -1));
+}
+
+
 void
 AddNotQual(Query *parsetree, Node *qual)
 {
@@ -485,9 +553,18 @@ nodeHandleViewRule(Node **nodePtr,
 				Aggreg	   *agg = (Aggreg *) node;
 
 				nodeHandleViewRule(&(agg->target), rtable, targetlist,
-								   rt_index, modified, sublevels_up);
+						   rt_index, modified, sublevels_up);
 			}
 			break;
+		/* This has to be done to make queries using groupclauses work on views */
+	        case T_GroupClause:
+		        {
+			  GroupClause  *group = (GroupClause *) node;
+			  
+			  nodeHandleViewRule((Node **) (&(group->entry)), rtable, targetlist,
+					     rt_index, modified, sublevels_up);
+			}
+		        break;
 		case T_Expr:
 			{
 				Expr	   *expr = (Expr *) node;
@@ -503,20 +580,40 @@ nodeHandleViewRule(Node **nodePtr,
 				int			this_varno = var->varno;
 				int			this_varlevelsup = var->varlevelsup;
 				Node	   *n;
-
+				
 				if (this_varno == rt_index &&
-					this_varlevelsup == sublevels_up)
-				{
-					n = FindMatchingTLEntry(targetlist,
-										 get_attname(getrelid(this_varno,
-															  rtable),
-													 var->varattno));
-					if (n == NULL)
-						*nodePtr = make_null(((Var *) node)->vartype);
-					else
-						*nodePtr = n;
-					*modified = TRUE;
-				}
+				    this_varlevelsup == sublevels_up)
+				  {				    
+				    n = FindMatchingTLEntry(targetlist,
+							    get_attname(getrelid(this_varno,
+										 rtable),
+									var->varattno));
+				    if (n == NULL)
+				      {
+					*nodePtr = make_null(((Var *) node)->vartype);
+				      }
+				    
+				    else
+				      /* This is a hack: The varlevelsup of the orignal
+                                       * variable and the new one should be the same.
+				       * Normally we adapt the node by changing a pointer
+				       * to point to a var contained in 'targetlist'. 
+				       * In the targetlist all varlevelsups are 0
+				       * so if we want to change it to the original value
+				       * we have to copy the node before! (Maybe this will
+				       * cause troubles with some sophisticated queries on
+				       * views?) */
+				      {
+					if(this_varlevelsup>0){
+					  *nodePtr = copyObject(n);
+					}
+					else {
+					  *nodePtr = n;
+					}
+					((Var *)*nodePtr)->varlevelsup = this_varlevelsup;
+				      }
+				    *modified = TRUE;
+				  }
 				break;
 			}
 		case T_List:
@@ -537,7 +634,20 @@ nodeHandleViewRule(Node **nodePtr,
 				Query	   *query = (Query *) sublink->subselect;
 
 				nodeHandleViewRule((Node **) &(query->qual), rtable, targetlist,
-								   rt_index, modified, sublevels_up + 1);
+						   rt_index, modified, sublevels_up + 1);
+				
+				/* We also have to adapt the variables used in sublink->lefthand
+				 * and sublink->oper */
+				nodeHandleViewRule((Node **) &(sublink->lefthand), rtable, 
+						 targetlist, rt_index, modified, sublevels_up);
+				
+				/* Make sure the first argument of sublink->oper points to the
+				 * same var as sublink->lefthand does otherwise we will
+				 * run into troubles using aggregates (aggno will not be
+				 * set correctly */				
+				pfree(lfirst(((Expr *) lfirst(sublink->oper))->args));
+				lfirst(((Expr *) lfirst(sublink->oper))->args) = 
+				  lfirst(sublink->lefthand);
 			}
 			break;
 		default:
@@ -553,9 +663,14 @@ HandleViewRule(Query *parsetree,
 			   int rt_index,
 			   int *modified)
 {
-
 	nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index,
 					   modified, 0);
 	nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist,
 					   rt_index, modified, 0);
+        /* The variables in the havingQual and groupClause also have to be adapted */
+	nodeHandleViewRule(&parsetree->havingQual, rtable, targetlist, rt_index,
+					   modified, 0);
+	nodeHandleViewRule((Node **) (&(parsetree->groupClause)), rtable, targetlist, rt_index,
+					   modified, 0);
 }
+
diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h
index a80cf48e135626e554a15f293d13085ab712b019..ab4e81f5437dfe68df193e79e4d972c16d114aa1 100644
--- a/src/include/optimizer/planmain.h
+++ b/src/include/optimizer/planmain.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: planmain.h,v 1.12 1998/04/15 15:29:57 momjian Exp $
+ * $Id: planmain.h,v 1.13 1998/07/19 05:49:25 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -64,6 +64,8 @@ extern void set_result_tlist_references(Result *resultNode);
 extern List *set_agg_tlist_references(Agg *aggNode);
 extern void set_agg_agglist_references(Agg *aggNode);
 extern void del_agg_tlist_references(List *tlist);
-extern List *check_having_qual_for_aggs(Node *clause, List *subplanTargetList);
+extern List *check_having_qual_for_aggs(Node *clause, 
+					List *subplanTargetList, List *groupClause);
+extern List *check_having_qual_for_vars(Node *clause, List *targetlist_so_far);
 
 #endif							/* PLANMAIN_H */
diff --git a/src/include/rewrite/rewriteManip.h b/src/include/rewrite/rewriteManip.h
index 9dbd73d2ef13fa113a940d8df91e493214759c23..f5934a896263143f80ee8fb1fe96f39ff82e0064 100644
--- a/src/include/rewrite/rewriteManip.h
+++ b/src/include/rewrite/rewriteManip.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rewriteManip.h,v 1.7 1998/02/26 04:43:08 momjian Exp $
+ * $Id: rewriteManip.h,v 1.8 1998/07/19 05:49:26 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,6 +23,8 @@ void
 ChangeVarNodes(Node *node, int old_varno, int new_varno,
 			   int sublevels_up);
 void		AddQual(Query *parsetree, Node *qual);
+void		AddHavingQual(Query *parsetree, Node *havingQual); 
+
 void		AddNotQual(Query *parsetree, Node *qual);
 void		FixResdomTypes(List *user_tlist);
 void		FixNew(RewriteInfo *info, Query *parsetree);