head	1.41;
access;
symbols
	release_4_2:1.41
	aix_ok:1.41
	Version_2_1:1.19
	C_Demo_1:1.8
	Retrieve_x_qual:1.5
	Retrieve_x_all:1.4
	Retrieve_x_1:1.3;
locks; strict;
comment	@ * @;


1.41
date	93.01.16.03.14.59;	author aoki;	state Exp;
branches;
next	1.40;

1.40
date	92.11.23.22.37.20;	author joey;	state Exp;
branches;
next	1.39;

1.39
date	92.07.23.15.37.36;	author joey;	state Exp;
branches;
next	1.38;

1.38
date	92.07.04.04.03.44;	author mao;	state Exp;
branches;
next	1.37;

1.37
date	92.07.03.03.28.46;	author hong;	state Exp;
branches;
next	1.36;

1.36
date	92.07.02.21.50.09;	author mer;	state Exp;
branches;
next	1.35;

1.35
date	92.06.28.03.49.14;	author mao;	state Exp;
branches;
next	1.34;

1.34
date	92.03.31.23.13.48;	author mer;	state Exp;
branches;
next	1.33;

1.33
date	92.02.25.15.30.38;	author clarsen;	state Exp;
branches;
next	1.32;

1.32
date	91.11.17.20.46.19;	author mer;	state Exp;
branches;
next	1.31;

1.31
date	91.11.15.16.26.16;	author hong;	state Exp;
branches;
next	1.30;

1.30
date	91.11.02.21.43.19;	author hong;	state Exp;
branches;
next	1.29;

1.29
date	91.09.22.22.05.07;	author hong;	state Exp;
branches;
next	1.28;

1.28
date	91.08.18.01.55.54;	author caetta;	state Exp;
branches;
next	1.27;

1.27
date	91.08.16.15.45.00;	author caetta;	state Exp;
branches;
next	1.26;

1.26
date	91.08.15.18.03.28;	author caetta;	state Exp;
branches;
next	1.25;

1.25
date	91.07.09.02.44.32;	author mao;	state Exp;
branches;
next	1.24;

1.24
date	91.05.29.23.13.59;	author hong;	state Exp;
branches;
next	1.23;

1.23
date	91.05.08.15.11.17;	author hong;	state Exp;
branches;
next	1.22;

1.22
date	91.04.27.14.18.32;	author hong;	state Exp;
branches;
next	1.21;

1.21
date	91.04.25.04.20.04;	author hong;	state Exp;
branches;
next	1.20;

1.20
date	91.04.24.12.14.33;	author hong;	state Exp;
branches;
next	1.19;

1.19
date	90.12.27.19.20.05;	author sp;	state Exp;
branches;
next	1.18;

1.18
date	90.11.02.11.19.49;	author goh;	state Exp;
branches;
next	1.17;

1.17
date	90.11.02.10.56.04;	author goh;	state Exp;
branches;
next	1.16;

1.16
date	90.09.25.16.36.41;	author kemnitz;	state Exp;
branches;
next	1.15;

1.15
date	90.05.30.18.56.55;	author cimarron;	state Exp;
branches;
next	1.14;

1.14
date	89.12.06.20.40.13;	author sp;	state Exp;
branches;
next	1.13;

1.13
date	89.12.06.14.42.49;	author sp;	state Exp;
branches;
next	1.12;

1.12
date	89.12.06.11.06.00;	author goh;	state Exp;
branches;
next	1.11;

1.11
date	89.12.04.11.40.16;	author goh;	state Exp;
branches;
next	1.10;

1.10
date	89.12.03.20.09.49;	author sp;	state Exp;
branches;
next	1.9;

1.9
date	89.10.01.15.03.13;	author ong;	state Exp;
branches;
next	1.8;

1.8
date	89.09.05.17.17.55;	author mao;	state C_Demo_1;
branches;
next	1.7;

1.7
date	89.08.30.09.04.57;	author cimarron;	state Exp;
branches;
next	1.6;

1.6
date	89.08.23.16.04.13;	author ong;	state Exp;
branches;
next	1.5;

1.5
date	89.08.04.14.30.04;	author goh;	state Exp;
branches;
next	1.4;

1.4
date	89.08.04.13.28.48;	author goh;	state Exp;
branches;
next	1.3;

1.3
date	89.08.01.14.36.16;	author goh;	state Exp;
branches;
next	1.2;

1.2
date	89.07.21.12.37.02;	author goh;	state Exp;
branches;
next	1.1;

1.1
date	89.07.18.15.16.51;	author ong;	state Exp;
branches;
next	;


desc
@routines to plan a single query.
@


1.41
log
@removed references to utils/fmgr.h and parser/parse.h
@
text
@
/*     
 *      FILE
 *     	planmain
 *     
 *      DESCRIPTION
 *     	Routines to plan a single query
 *     
 */
/* RcsId ("$Header: /home2/aoki/postgres/src/backend/planner/plan/RCS/planmain.c,v 1.40 1992/11/23 22:37:20 joey Exp aoki $"); */

/*     
 *      EXPORTS
 *     		Plan query_planner();
 */


#include "nodes/pg_lisp.h"
#include "nodes/plannodes.h"
#include "nodes/plannodes.a.h"
#include "nodes/relation.h"
#include "nodes/relation.a.h"

#include "parse.h"

#include "planner/internal.h"
#include "planner/allpaths.h"
#include "planner/clause.h"
#include "planner/createplan.h"
#include "planner/keys.h"
#include "planner/planmain.h"
#include "planner/setrefs.h"
#include "planner/sortresult.h"
#include "planner/sortresult.h"
#include "planner/tlist.h"
#include "planner/xfunc.h"
#include "tcop/dest.h"
#include "utils/log.h"
#include "nodes/mnodes.h"
#include "utils/mcxt.h"

extern int testFlag;

/*    
 *    	query_planner
 *    
 *    	Routine to create a query plan.  It does so by first creating a
 *    	subplan for the topmost level of attributes in the query.  Then,
 *    	it modifies all target list and qualifications to consider the next
 *    	level of nesting and creates a plan for this modified query by
 *    	recursively calling itself.  The two pieces are then merged together
 *    	by creating a result node that indicates which attributes should
 *    	be placed where and any relation level qualifications to be
 *    	satisfied.
 *    
 *    	'command-type' is the query command, e.g., retrieve, delete, etc.
 *    	'tlist' is the target list of the query
 *    	'qual' is the qualification of the query
 *    	'currentlevel' is the current nesting level
 *    	'maxlevel' is the maximum nesting level in this query
 *    
 *    	Returns a query plan.
 *    
 */

/*  .. init-query-planner, query_planner    */

Plan
query_planner (command_type,tlist,qual,currentlevel,maxlevel)
     int command_type;
     List tlist,qual;
     int currentlevel;
     int maxlevel ;
{
     LispValue constant_qual = LispNil;
     LispValue sortkeys = LispNil;
     LispValue flattened_tlist = LispNil;
     List 	level_tlist = LispNil;
     List	result_of_flatten_tlist = LispNil;
     List	agg_tlist = LispNil;
     List	all_but_agg_tlist = LispNil;
     int	aggidnum = -17; /* okay, a hack on uniquness */
     Plan	thePlan = (Plan)NULL;
     Plan	subplan = (Plan)NULL;
     List	subtlist = LispNil;
     Plan 	restplan = (Plan)NULL;
     List	resttlist = LispNil;
     List	relation_level_clauses = LispNil;
     Plan 	plan = (Plan)NULL;

     /*    For the topmost nesting level, */
     /* 1. Pull out any non-variable qualifications so these can be put in */
     /*    the topmost result node.  The opids for the remaining */
     /*    qualifications will be changed to regprocs later. */
     /*    ------
      *    NOTE: we used to have one field called 'opno' in the Oper
      *    nodes which used to be also be called 'opid' in some comments.
      *    This field was either the pg_operator oid, or the
      *    regproc oid. However now we have two separate
      *    fields, the 'opno' (pg_operator oid) and the 'opid' (pg_proc
      *    oid) so things are a little bit more clear now...   [sp.]
      *    ------
      */
     /* 2. Determine the keys on which the result is to be sorted. */
     /* 3. Create a target list that consists solely of (resdom var) target */
     /*    list entries, i.e., contains no arbitrary expressions. */
     
     if ( currentlevel == 1) {
	 /* A command without a target list or qualification is an error, */
	 /* except for "delete foo". */
	 
	 if (null (tlist) && null (qual)) {
	     if ( command_type == DELETE ||
	     /* Total hack here. I don't know how to handle
		statements like notify in action bodies.
		Notify doesn't return anything but
		scans a system table. */
		 command_type == NOTIFY) {
		 return ((Plan)make_seqscan(LispNil, LispNil,
				       (Index)CInteger(_query_result_relation_),
				       (Plan)NULL));
	     } else
	       return((Plan)NULL);
	 }
	 constant_qual = pull_constant_clauses (qual);
	 qual = nset_difference (qual,constant_qual);
	 fix_opids (constant_qual);
	 sortkeys = relation_sortkeys (tlist);
	 /* flatten_tlist will now return (var, aggs, rest) */

	 result_of_flatten_tlist = flatten_tlist(tlist);

	 flattened_tlist = CAR(result_of_flatten_tlist);
	 agg_tlist = CADR(result_of_flatten_tlist);

	 result_of_flatten_tlist = CDR(result_of_flatten_tlist);
	 all_but_agg_tlist = CADR(result_of_flatten_tlist);
	 if (flattened_tlist)
	   level_tlist = flattened_tlist;
	 else if (tlist)
	   level_tlist = all_but_agg_tlist;
	   /* orig_tlist minus the aggregates */
	 else
	   level_tlist = (List)NULL;
     }

  if(agg_tlist) {
     if(all_but_agg_tlist) {
	thePlan = query_planner(command_type,
		all_but_agg_tlist, qual, currentlevel, maxlevel);
     }
     else {
	 /* all we have are aggregates */
	 thePlan = (Plan)make_agg(CAR(agg_tlist), --aggidnum);
	 /* also, there should never be a case by now where we neither 
	  * have aggs nor all_but_aggs
	  */
	  agg_tlist = CDR(agg_tlist);
     }
     if(agg_tlist != NULL) {  /* are there any aggs left */
	   thePlan = make_aggplan(thePlan, agg_tlist, aggidnum);
      }
      return(thePlan);
   }

     /*    A query may have a non-variable target list and a non-variable */
     /*    qualification only under certain conditions: */
     /*    - the query creates all-new tuples, or */
     /*   - the query is a replace (a scan must still be done in this case). */

     if ((0 == maxlevel || 
	  (1 == currentlevel && null (flattened_tlist))) &&
	 null (qual)) {
	  switch (command_type) {
	     case RETRIEVE : 
	     case APPEND :
	       return ((Plan)make_result (tlist,
				    LispNil,
				    constant_qual,
				    (Plan)NULL,
				    (Plan)NULL));
	       break;

	     case DELETE :
	     case REPLACE : 
	       {
		    /* XXX - let form, maybe incorrect */
		   SeqScan scan = make_seqscan (tlist,
					       LispNil,
					       (Index)CInteger(
						   _query_result_relation_),
					       (Plan)NULL);
		   if ( consp (constant_qual) ) {
		       return ((Plan)make_result (tlist,
						 LispNil,
						 constant_qual,
						 (Plan)scan,
						 (Plan)NULL));
		   } 
		   else {
		       return ((Plan)scan);
		   } 
	       }
	       break;
	       
	     default: /* return nil */
	       return((Plan)NULL);
	  }
     }
/*    Find the subplan (access path) for attributes at this nesting level */
/*    and destructively modify the target list of the newly created */
/*    subplan to contain the appropriate join references. */
	  
     subplan = subplanner (level_tlist,
				tlist,
				qual,
				currentlevel,
				sortkeys);
     
     subtlist = get_qptargetlist (subplan);
     set_tlist_references (subplan);

/*    If there are further nesting levels, call the planner again to */
/*    create subplans for lower levels of nesting.  Modify the target */
/*    list and qualifications to reflect the new nesting level. */

       if (currentlevel != maxlevel) {
	    elog(WARN, "level mismatch -- should never happen with new nested dot parsing scheme!");
       }
/*    Build a result node linking the plan for deeper nesting levels and */
/*    the subplan for this level.  Note that a plan that has no right */
/*    subtree may still have relation level and constant quals, so we */
/*    still have to build an appropriate result node. */

     relation_level_clauses = pull_relation_level_clauses (qual);
     
     if ( restplan ||
	 relation_level_clauses ||
	 constant_qual) {
	  List resttlist = LispNil;
	  List subtlist = LispNil;
	  Plan plan;
	  
	  if ( restplan ) 
	    resttlist = get_qptargetlist (restplan);
	  subtlist = get_qptargetlist (subplan);
	  
	  plan = (Plan)make_result (new_result_tlist (tlist,
						      subtlist,
						      resttlist,
						      currentlevel,
						      valid_sortkeys(sortkeys)),
				   new_result_qual(relation_level_clauses,
						   subtlist,
						   resttlist,
						   currentlevel),
				    constant_qual,
				   subplan,
				   restplan);
	  /*
	   * Change all varno's of the Result's node target list.
	   */
	  set_result_tlist_references((Result)plan);

	  if ( valid_numkeys (sortkeys) ) 
	    return (sort_level_result (plan, CInteger(sortkeys)));
	  else 
	    return (plan);
     }

     /*
      * fix up the flattened target list of the plan root node so that
      * expressions are evaluated.  this forces expression evaluations
      * that may involve expensive function calls to be delayed to
      * the very last stage of query execution.  this could be bad.
      * but it is joey's responsibility to optimally push these
      * expressions down the plan tree.  -- Wei
      */
     set_qptargetlist (subplan, flatten_tlist_vars (tlist,
						get_qptargetlist (subplan)));
     /*
      * Destructively modify the query plan's targetlist to add fjoin
      * lists to flatten functions that return sets of base types
      */
     set_qptargetlist(subplan, generate_fjoin(get_qptargetlist(subplan)));

	/*    If a sort is required, explicitly sort this subplan since: */
	/*    there is only one level of attributes in this query, and */
	/*the sort spans across expressions and/or multiple relations and so */
	/*    	indices were not considered in planning the sort. */

     if ( valid_numkeys (sortkeys) ) 
       return (sort_level_result (subplan,CInteger(sortkeys)));
     else 
       return (subplan);

}  /* function end  */

/*    
 *    	subplanner
 *    
 *    	Subplanner creates an entire plan consisting of joins and scans
 *    	for processing a single level of attributes.  Nested attributes are 
 *    	transparent (i.e., essentially ignored) from here on.
 *    
 *    	'flat-tlist' is the flattened target list
 *	--which now is of the form (vars, aggs)--, jc
 *    	'original-tlist' is the unflattened target list
 *    	'qual' is the qualification to be satisfied
 *    	'level' is the current nesting level
 *    
 *    	Returns a subplan.
 *    
 */

/*  .. query_planner    */

Plan
subplanner (flat_tlist,original_tlist,qual,level,sortkeys)
     LispValue flat_tlist,original_tlist,qual,sortkeys ;
     int level;
{
    Rel final_relation;
    List final_relation_list;

     /* Initialize the targetlist and qualification, adding entries to */
     /* *query-relation-list* as relation references are found (e.g., in the */
     /*  qualification, the targetlist, etc.) */

    _base_relation_list_ = LispNil;
    _join_relation_list_ = LispNil;
    initialize_targetlist (flat_tlist);
    initialize_qualification (qual);

    
/* Find all possible scan and join paths. */
/* Mark all the clauses and relations that can be processed using special */
/* join methods, then do the exhaustive path search. */

    initialize_join_clause_info (_base_relation_list_);
    final_relation_list = find_paths (_base_relation_list_,
					level,
					sortkeys);
    if (final_relation_list)
      final_relation = (Rel)CAR (final_relation_list);
    else
      final_relation = (Rel)LispNil;
     
/*
** Perform Predicate Migration on each path, to optimize and correctly assess
** the cost of each before choosing the cheapest one.  -- JMH, 11/16/92
**
** Needn't do so if the top rel is pruneable: that means there's no expensive
** functions left to pull up.  -- JMH, 11/22/92
*/
    if (XfuncMode != XFUNC_OFF && XfuncMode != XFUNC_NOPM && 
	XfuncMode != XFUNC_NOPULL && !get_pruneable(final_relation))
     {
	 LispValue pathnode;
	 foreach(pathnode, get_pathlist(final_relation))
	  {
	      if (xfunc_do_predmig((Path)CAR(pathnode)))
		set_cheapest(final_relation, get_pathlist(final_relation));
	  }
     }

/*    If we want a sorted result and indices could have been used to do so, */
/*    then explicitly sort those paths that weren't sorted by indices so we */
/*  can determine whether using the implicit sort (index) is better than an */
/*  explicit one. */

     if ( valid_sortkeys (sortkeys)) {
	 sort_relation_paths (get_pathlist (final_relation),
			       sortkeys,
			      final_relation,
			      compute_targetlist_width(original_tlist));
     }

/*    Determine the cheapest path and create a subplan corresponding to it. */
    if (final_relation) {
      if (testFlag) {
	  List planlist = LispNil;
	  List pathlist = LispNil;
	  LispValue x;
	  Path path;
	  Plan plan;
	  Choose chooseplan;
	  pathlist = get_pathlist(final_relation);
	  foreach (x, pathlist) {
	      path = (Path)CAR(x);
	      plan = create_plan(path);
	      planlist = nappend1(planlist, (LispValue)plan);
	    }
	  chooseplan = RMakeChoose();
	  set_chooseplanlist(chooseplan, planlist);
	  set_qptargetlist((Plan)chooseplan, get_qptargetlist(plan));
	  return (Plan)chooseplan;
	}
      return (create_plan ((Path)get_cheapestpath (final_relation)));
     }
    else {
	printf(" Warn: final relation is nil \n");
	return(create_plan ((Path)NULL));
    }
    
}  /* function end  */

Result
make_result( tlist,resrellevelqual,resconstantqual,left,right)
     List tlist;
     List resrellevelqual,resconstantqual;
     Plan left,right;
{
    Result node = RMakeResult();
    
    tlist = generate_fjoin(tlist);
    set_cost((Plan) node, 0.0);
    set_fragment((Plan) node, 0);
    set_state((Plan) node, NULL);
    set_qptargetlist((Plan)node, tlist);
    set_qpqual((Plan) node, LispNil);
    set_lefttree((Plan)node, (PlanPtr)left);
    set_righttree((Plan)node, (PlanPtr)right);

    set_resrellevelqual(node, resrellevelqual); 
    set_resconstantqual(node, resconstantqual); 
    set_resstate(node, NULL);
    
    return(node);
} 

/* for modifying in case of aggregates.
 * we know that there are aggregates in the tlist*/
Plan
make_aggplan(subplan, agg_tlist, aggidnum)
    Plan subplan;
    List agg_tlist;
    int aggidnum;
{
     List agg_tl_entry = LispNil;
     List add_to_tl = LispNil;
     NestLoop joinnode = (NestLoop)NULL;
     LispValue entry = LispNil;
     List level_tlist = LispNil;
     Agg aggnode;
/*    extern search_quals(); */

	/* we're assuming that subplan is not null from the caller*/
	agg_tl_entry = CAR(agg_tlist);
	aggnode = make_agg(agg_tl_entry, --aggidnum);

        set_qptargetlist(subplan, nconc(get_qptargetlist(subplan),
					 get_qptargetlist((Plan)aggnode)));
	level_tlist = get_qptargetlist(subplan);
	joinnode = make_nestloop(level_tlist, LispNil, (Plan)aggnode,
							  subplan);
	/* inner tree is the aggregate, outer tree is the rest of
	 * the plan.  quals are nil here since we don't have aggregate
	 * functions yet.
	 */

	if(CDR(agg_tlist)) {  /* is this the last agg_tlist entry? */
	   /* if not */
	   return make_aggplan((Plan)joinnode, CDR(agg_tlist), aggidnum);
            /* XXX jc.  type problem with joinnode and Plan subplan? */
         }
	 else { /* if so */
	      return((Plan) joinnode);
	 }
}


	

bool
plan_isomorphic(p1, p2)
Plan p1, p2;
{
    if (p1 == NULL) return (p2 == NULL);
    if (p2 == NULL) return (p1 == NULL);
    if (IsA(p1,Join) && IsA(p2,Join)) {
	return (plan_isomorphic(get_lefttree(p1), get_lefttree(p2)) &&
	        plan_isomorphic(get_righttree(p1), get_righttree(p2)));
      }
    if (IsA(p1,Scan) && IsA(p2,Scan)) {
	if (get_scanrelid((Scan)p1) == get_scanrelid((Scan)p2))
	    if (get_scanrelid((Scan)p1) == _TEMP_RELATION_ID_)
		return plan_isomorphic(get_lefttree(p1), get_lefttree(p2));
	    else
		return true;
	else if (get_scanrelid((Scan)p1) == _TEMP_RELATION_ID_)
	    return plan_isomorphic(get_lefttree(p1), p2);
	else if (get_scanrelid((Scan)p2) == _TEMP_RELATION_ID_)
	    return plan_isomorphic(p1, get_lefttree(p2));
	return false;
      }
    if (IsA(p1,Temp) || IsA(p1,Hash) ||
	(IsA(p1,Scan) && get_scanrelid((Scan)p1) == _TEMP_RELATION_ID_))
	return plan_isomorphic(get_lefttree(p1), p2);
    if (IsA(p2,Temp) || IsA(p2,Hash) ||
	(IsA(p2,Scan) && get_scanrelid((Scan)p2) == _TEMP_RELATION_ID_))
	return plan_isomorphic(p1, get_lefttree(p2));
    return false;
}

List
group_planlist(planlist)
List	planlist;
{
    List plangroups = LispNil;
    Plan p1, p2;
    List plist;
    List g, x;

    plist = planlist;
    while (!lispNullp(plist)) {
	p1 = (Plan)CAR(plist);
	g = lispCons((LispValue)p1, LispNil);
	foreach (x, CDR(plist)) {
	    p2 = (Plan)CAR(x);
	    if (plan_isomorphic(p1, p2)) {
		g = nappend1(g, (LispValue)p2);
	      }
	  }
	plist = nset_difference(plist, g);
	plangroups = nappend1(plangroups, g);
      }
    return plangroups;
}

bool
allNestLoop(plan)
Plan	plan;
{
    if (plan == NULL) return true;
    if (IsA(plan,Temp) ||
	(IsA(plan,Scan) && get_scanrelid((Scan)plan) == _TEMP_RELATION_ID_))
	return allNestLoop(get_lefttree(plan));
    if (IsA(plan,NestLoop)) {
	return allNestLoop(get_lefttree(plan)) &&
	       allNestLoop(get_righttree(plan));
      }
    if (IsA(plan,Join))
	return false;
    return true;
}

Plan
pickNestLoopPlan(plangroup)
List	plangroup;
{
    LispValue x;
    Plan p;

    foreach (x, plangroup) {
	p = (Plan)CAR(x);
	if (allNestLoop(p))
	    return p;
      }
    return NULL;
}

void
setPlanStats(p1, p2)
Plan p1, p2;
{
    if (p1 == NULL || p2 == NULL)
	return;
    if (IsA(p1,Join) && IsA(p2,Join)) {
	set_plan_size(p2, get_plan_size(p1));
	setPlanStats(get_lefttree(p1), get_lefttree(p2));
	/*
	setPlanStats(get_righttree(p1), get_righttree(p2));
	*/
	return;
      }
    if (IsA(p1,Temp) || IsA(p1,Hash) ||
	(IsA(p1,Scan) && get_scanrelid((Scan)p1) == _TEMP_RELATION_ID_)) {
	setPlanStats(get_lefttree(p1), p2);
	return;
      }
    if (IsA(p2,Temp) || IsA(p2,Hash) ||
	(IsA(p2,Scan) && get_scanrelid((Scan)p2) == _TEMP_RELATION_ID_)) {
	set_plan_size(p2, get_plan_size(p1));
	setPlanStats(p1, get_lefttree(p2));
	return;
      }
    if (IsA(p1,Scan) && IsA(p2,Scan)) {
	set_plan_size(p2, get_plan_size(p1));
	return;
      }
    return;
}

void
resetPlanStats(p)
Plan p;
{
    if (p == NULL) return;
    set_plan_size(p, 0);
    if (IsA(p,Join)) {
	resetPlanStats(get_lefttree(p));
	resetPlanStats(get_righttree(p));
	return;
      }
    if (IsA(p,Scan)) {
	if (get_scanrelid((Scan)p) == _TEMP_RELATION_ID_)
	   resetPlanStats(get_lefttree(p));
	return;
      }
    resetPlanStats(get_lefttree(p));
    return;
}

void
setPlanGroupStats(plan, planlist)
Plan	plan;
List	planlist;
{
    List x;
    Plan p;

    foreach (x, planlist) {
	p = (Plan)CAR(x);
	setPlanStats(plan, p);
     }
}

bool _exec_collect_stats_ = false;

/*
 * XXX mao speaking:
 *
 *	i assume that this routine is used by some planner wizard to
 *	collect actual plan execution costs, and that it's not run
 *	during ordinary postgres processing.  the planner shouldn't
 *	be executing queries directly, right?
 */

List
setRealPlanStats(parsetree, planlist)
List	parsetree;
List	planlist;
{
    List plangroups;
    List plangroup;
    LispValue x;
    List ordered_planlist;
    Plan nlplan;

    _exec_collect_stats_ = true;
    plangroups = group_planlist(planlist);
    ordered_planlist = LispNil;
    foreach (x, plangroups) {
	plangroup = CAR(x);
	nlplan = pickNestLoopPlan(plangroup);
	if (nlplan == NULL) {
	    elog(NOTICE, "no nestloop plan in plan group!");
	    break;
	  }
	if (IsA(nlplan,Join)) {
	    resetPlanStats(nlplan);
	    p_plan(nlplan);
	    ResetUsage();
	    ProcessQuery(parsetree, nlplan, (char *) NULL, (ObjectId *) NULL,
			 0, None);
	    ShowUsage();
	    plangroup = nLispRemove(plangroup, (LispValue)nlplan);
	    setPlanGroupStats(nlplan, plangroup);
	  }
	else {
	    ordered_planlist = plangroup;
	    break;
	  }
	ordered_planlist = nconc(ordered_planlist, plangroup);
      }
    _exec_collect_stats_ = false;
    return ordered_planlist;
}

bool
plan_contain_redundant_hashjoin(plan)
Plan plan;
{
    Plan outerplan, innerplan;
    int outerpages, innerpages;
    if (plan == NULL)
	return false;
    if (IsA(plan,HashJoin)) {
	outerplan = (Plan) get_lefttree(plan);
	innerplan = (Plan) get_lefttree((Plan)get_righttree(plan));
	outerpages = page_size(get_plan_size(outerplan), 
			       get_plan_width(outerplan));
	innerpages = page_size(get_plan_size(innerplan),
			       get_plan_width(innerplan));
	if (!IsA(outerplan,Join) && outerpages < innerpages)
	    return true;
      }
    if (IsA(plan,Join))
	return plan_contain_redundant_hashjoin(get_lefttree(plan)) ||
	       plan_contain_redundant_hashjoin(get_righttree(plan));
    if (IsA(plan,Temp) || IsA(plan,Hash) ||
	(IsA(plan,Scan) && get_scanrelid((Scan)plan) == _TEMP_RELATION_ID_))
	return plan_contain_redundant_hashjoin(get_lefttree(plan));
    return false;
}

List
pruneHashJoinPlans(planlist)
List planlist;
{
    LispValue x;
    Plan plan;
    List retlist;

    retlist = LispNil;
    foreach (x, planlist) {
	plan = (Plan)CAR(x);
	if (!plan_contain_redundant_hashjoin(plan))
	    retlist = nappend1(retlist, (LispValue)plan);
      }
    return retlist;
}
@


1.40
log
@added call to xfunc_do_predmig
@
text
@d10 1
a10 1
/* RcsId ("$Header: /var/home/hellers/pg/src/planner/plan/RCS/planmain.c,v 1.39 1992/07/23 15:37:36 joey Exp $"); */
d24 1
a24 1
#include "parser/parse.h"
@


1.39
log
@fix call to nconc to set result to equal first argument.  this
protects us if first argument is NULL and cannot be conc'ed.
@
text
@d10 1
a10 1
/* RcsId ("$Header: /private/joey/pg/src/planner/plan/RCS/planmain.c,v 1.38 1992/07/04 04:03:44 mao Exp joey $"); */
d36 1
d349 18
d378 1
a379 1
    
@


1.38
log
@fixes for arrays, array refs, and nested dots
@
text
@d10 1
a10 1
/* RcsId ("$Header: /private/mao/postgres/src/planner/plan/RCS/planmain.c,v 1.37 1992/07/03 03:28:46 hong Exp mao $"); */
d433 3
a435 2
	level_tlist = nconc(get_qptargetlist(subplan),
					 get_qptargetlist((Plan)aggnode));
@


1.37
log
@cleaned up final targetlist generation part, put generate_fjoin() in place
@
text
@d10 1
a10 1
/* RcsId ("$Header: plan/RCS/planmain.c,v 1.36 92/07/02 21:50:09 mer Exp Locker: hong $"); */
d226 2
a227 10
       if ( !(currentlevel == maxlevel ) ) {
	    restplan = query_planner (command_type,
				      new_level_tlist (level_tlist,
						       subtlist,
						       currentlevel),
				      new_level_qual (qual,
						      subtlist,
						      currentlevel),
				      currentlevel + 1,
				      maxlevel);
@


1.36
log
@special case Result plan fjoin generation in the target list
@
text
@d10 1
a10 1
/* RcsId ("$Header: /private/mer/pg/src/planner/plan/RCS/planmain.c,v 1.35 1992/06/28 03:49:14 mao Exp mer $"); */
d277 10
a286 11
	/*    Remodify the target list of the subplan so it no longer is */
	/*    'flattened', unless this has already been done in create_plan */
	/*    for a path that had to be explicitly sorted. */

     if ( 1 == maxlevel &&
	 !(IsA(subplan,Temp) || 
	   (IsA(subplan,SeqScan) && 
	    get_lefttree(subplan) && 
	    IsA (get_lefttree (subplan),Temp)))) {
	  set_qptargetlist (subplan,
			    flatten_tlist_vars (tlist,
d288 6
a293 1
	}
d380 1
a380 1
	      plan = create_plan(path, original_tlist);
d388 1
a388 2
      return (create_plan ((Path)get_cheapestpath (final_relation),
			   original_tlist));
d392 1
a392 1
	return(create_plan ((Path)NULL, original_tlist));
@


1.35
log
@rearrange parse, plan to support postquel function invocations
@
text
@d10 1
a10 1
/* RcsId ("$Header: /private/mao/postgres/src/planner/plan/RCS/planmain.c,v 1.34 1992/03/31 23:13:48 mer Exp mao $"); */
d402 1
@


1.34
log
@change accessor functions into macros
@
text
@d10 1
a10 1
/* RcsId ("$Header: /users/mer/pg/src/planner/plan/RCS/planmain.c,v 1.33 1992/02/25 15:30:38 clarsen Exp mer $"); */
d615 9
d649 2
a650 1
	    ProcessQuery(parsetree, nlplan, None);
@


1.33
log
@async portals.
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.32 91/11/17 20:46:19 mer Exp Locker: clarsen $"); */
d384 1
a384 1
      return (create_plan (get_cheapestpath (final_relation),
d407 2
a408 2
    set_lefttree((Plan)node, left);
    set_righttree((Plan)node, right);
d665 1
a665 1
	innerplan = (Plan) get_lefttree(get_righttree(plan));
@


1.32
log
@prototyping
@
text
@d10 1
a10 1
/* RcsId ("$Header: /users/mer/postgres/src/planner/plan/RCS/planmain.c,v 1.31 1991/11/15 16:26:16 hong Exp mer $"); */
d112 6
a117 1
	     if ( command_type == DELETE ) {
a173 1
	       
@


1.31
log
@planner prototyping
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.30 91/11/02 21:43:19 hong Exp $"); */
d373 1
a373 1
	      planlist = nappend1(planlist, plan);
d498 1
a498 1
	g = lispCons(p1, LispNil);
d502 1
a502 1
		g = nappend1(g, p2);
d638 1
a638 1
	    plangroup = nLispRemove(plangroup, nlplan);
d690 1
a690 1
	    retlist = nappend1(retlist, plan);
@


1.30
log
@cleaned up bushy tree plan generation code
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.29 91/09/22 22:05:07 hong Exp $"); */
d30 1
d32 1
a41 6
/* ----------------
 *	Result creator declaration
 * ----------------
 */
extern Result RMakeResult();
extern Choose RMakeChoose();
a89 2
     extern Plan subplanner();
     
d113 3
a115 5
		 return ((Plan)make_seqscan((List) NULL, 
					     (List) NULL,
					     (Index) CInteger(
						_query_result_relation_),
					     (Node) NULL ));
d155 1
a155 1
	   thePlan = (Plan)make_aggplan(thePlan, agg_tlist, aggidnum);
d175 2
a176 2
				    LispNil,
				    LispNil));
d185 1
a185 1
					       (Index) CInteger(
d187 1
a187 1
					       LispNil);
d192 2
a193 2
						 scan,
						 LispNil));
d266 1
a266 1
	  set_result_tlist_references(plan);
d269 1
a269 1
	    return (sort_level_result (plan,sortkeys));
d292 1
a292 1
       return (sort_level_result (subplan,sortkeys));
d319 2
a320 1
     LispValue flat_tlist,original_tlist,qual,level,sortkeys ;
d377 1
a377 1
	  set_qptargetlist(chooseplan, get_qptargetlist(plan));
d385 1
a385 1
	return(create_plan (LispNil,original_tlist));
a416 1
    LispValue agg_tlist;
d418 1
d434 2
a435 2
					    get_qptargetlist(aggnode));
	joinnode = make_nestloop(level_tlist, LispNil, aggnode,
d444 1
a444 1
	   return make_aggplan(joinnode, CDR(agg_tlist), aggidnum);
d466 2
a467 2
	if (get_scanrelid(p1) == get_scanrelid(p2))
	    if (get_scanrelid(p1) == _TEMP_RELATION_ID_)
d471 1
a471 1
	else if (get_scanrelid(p1) == _TEMP_RELATION_ID_)
d473 1
a473 1
	else if (get_scanrelid(p2) == _TEMP_RELATION_ID_)
d478 1
a478 1
	(IsA(p1,Scan) && get_scanrelid(p1) == _TEMP_RELATION_ID_))
d481 1
a481 1
	(IsA(p2,Scan) && get_scanrelid(p2) == _TEMP_RELATION_ID_))
d517 1
a517 1
	(IsA(plan,Scan) && get_scanrelid(plan) == _TEMP_RELATION_ID_))
d558 1
a558 1
	(IsA(p1,Scan) && get_scanrelid(p1) == _TEMP_RELATION_ID_)) {
d563 1
a563 1
	(IsA(p2,Scan) && get_scanrelid(p2) == _TEMP_RELATION_ID_)) {
d587 1
a587 1
	if (get_scanrelid(p) == _TEMP_RELATION_ID_)
d673 1
a673 1
	(IsA(plan,Scan) && get_scanrelid(plan) == _TEMP_RELATION_ID_))
@


1.29
log
@mixed up left and right tree in hashjoin before
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.28 91/08/18 01:55:54 caetta Exp $"); */
a39 1
extern GlobalMemory ParserPlannerContext;
d330 1
d336 2
a337 1
    _query_relation_list_ = LispNil;
d346 2
a347 2
    initialize_join_clause_info (_query_relation_list_);
    _query_relation_list_ = find_paths (_query_relation_list_,
d350 2
a351 2
    if (_query_relation_list_)
      final_relation = (Rel)CAR (_query_relation_list_);
a376 3
	  /*
	  MemoryContextSwitchTo(ParserPlannerContext);
	  */
d523 3
@


1.28
log
@a kinder, gentler planner...
@
text
@d10 1
a10 1
/* RcsId ("$Header: planner/plan/RCS/planmain.c,v 1.27 91/08/16 15:45:00 caetta Exp Locker: caetta $"); */
d666 2
a667 2
	outerplan = (Plan) get_lefttree(get_lefttree(plan));
	innerplan = (Plan) get_righttree(plan);
d672 1
a672 1
	if (!IsA(outerplan,Join) && outerpages > innerpages)
@


1.27
log
@fix from being broken by aggregates
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.26 91/08/15 18:03:28 caetta Exp $"); */
a96 1
     
d444 2
a445 2
	joinnode = make_nestloop(level_tlist, LispNil, subplan,
							  aggnode);
@


1.26
log
@for aggregates, building the plan
@
text
@d10 1
a10 1
/* RcsId ("$Header: planner/plan/RCS/planmain.c,v 1.25 91/07/09 02:44:32 mao Exp Locker: caetta $"); */
d85 1
d87 1
d141 1
d145 1
a145 1
	   level_tlist = CADR(result_of_flatten_tlist);
d151 19
d176 1
a176 1
	  (1 == currentlevel && null (result_of_flatten_tlist))) &&
d219 1
a219 2
     if(level_tlist != NULL) {
	 subplan = subplanner (level_tlist,
d224 1
a224 16
     }
     else if(agg_tlist != NULL) {
     /* level_tlist was null in this case so our base plan is the aggnode */

        subplan = (Plan)make_agg(CAR(agg_tlist), --aggidnum);

	/* this calls the planner on the inner query, builds the Agg node,
	 * sets the appropriate fields, and returns the Agg node.
	 */
        agg_tlist = CDR(agg_tlist);
     }
     /* we're assuming we Have a targetlist at this point */
     if(agg_tlist != NULL) {
	/* are there any aggs left...*/
	subplan = (Plan)make_aggplan(subplan, agg_tlist, aggidnum);
     }
@


1.25
log
@get rid of compile-time warning
@
text
@d10 1
a10 1
/* RcsId ("$Header: /users/mao/postgres/src/planner/plan/RCS/planmain.c,v 1.24 1991/05/29 23:13:59 hong Exp mao $"); */
d83 3
d131 8
a138 1
	 flattened_tlist = flatten_tlist (tlist);
d142 2
a143 1
	   level_tlist = tlist;
d154 1
a154 1
	  (1 == currentlevel && null (flattened_tlist))) &&
d197 22
a218 5
     subplan = subplanner (level_tlist,
			   tlist,
			   qual,
			   currentlevel,
			   sortkeys);
d310 1
d416 42
@


1.24
log
@some changes that only affect my experiments
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.23 91/05/08 15:11:17 hong Exp $"); */
d590 2
a591 2
	outerplan = get_lefttree(get_lefttree(plan));
	innerplan = get_righttree(plan);
@


1.23
log
@some changes in wei's special code, no affect to anyone else
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.22 91/04/27 14:18:32 hong Exp $"); */
d35 3
d40 1
d342 3
d396 1
a396 3
	        plan_isomorphic(get_righttree(p1), get_righttree(p2))) ||
	       (plan_isomorphic(get_lefttree(p1), get_righttree(p2)) &&
		plan_isomorphic(get_righttree(p1), get_lefttree(p2)));
d481 4
a484 8
	if (plan_isomorphic(get_lefttree(p1), get_lefttree(p2))) {
	    setPlanStats(get_lefttree(p1), get_lefttree(p2));
	    setPlanStats(get_righttree(p1), get_righttree(p2));
	  }
	else {
	    setPlanStats(get_lefttree(p1), get_righttree(p2));
	    setPlanStats(get_righttree(p1), get_lefttree(p2));
	  }
d487 2
a488 7
    if (IsA(p1,Scan) && IsA(p2,Scan)) {
	set_plan_size(p2, get_plan_size(p1));
	if (get_scanrelid(p1) == _TEMP_RELATION_ID_)
	    setPlanStats(get_lefttree(p1), get_lefttree(p2));
	return;
      }
    if (IsA(p1,Temp)) {
d492 2
a493 1
    if (IsA(p2,Temp)) {
d498 4
d554 1
d558 4
d564 2
d567 3
a569 1
	    setPlanGroupStats(nlplan, nLispRemove(plangroup, nlplan));
d571 2
a572 1
	else
d574 2
d578 20
a597 3
    ordered_planlist = LispNil;
    foreach (x, plangroups) {
	ordered_planlist = nconc(ordered_planlist, CAR(x));
d599 24
a622 1
    return ordered_planlist;
@


1.22
log
@added code to collect real execution stats for plans
this has to do with my experiments only.
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.21 91/04/25 04:20:04 hong Exp Locker: hong $"); */
a332 1
	  List prunePathListForTest();
a337 1
	  pathlist = prunePathListForTest(pathlist);
a381 62
pathShouldPruned(path, order_expected)
Path path;
bool order_expected;
{
    if (IsA(path,MergePath)) {
	return pathShouldPruned(get_outerjoinpath(path), 
				!get_outersortkeys(path)) ||
	       pathShouldPruned(get_innerjoinpath(path), 
				!get_innersortkeys(path));
      }
    if (IsA(path,HashPath)) {
	return pathShouldPruned(get_outerjoinpath(path), false) ||
	       pathShouldPruned(get_innerjoinpath(path), false);
      }
    if (IsA(path,JoinPath)) {
	if (!IsA(get_innerjoinpath(path),IndexPath) &&
	    !IsA(get_innerjoinpath(path),JoinPath) &&
	    length(get_relids(get_parent(get_innerjoinpath(path)))) == 1)
	   return true;
	return pathShouldPruned(get_outerjoinpath(path), order_expected) ||
	       pathShouldPruned(get_innerjoinpath(path), false);
      }
    if (IsA(path,IndexPath)) {
	return lispNullp(get_indexqual(path)) && !order_expected;
      }
    return false;
}

List
prunePathListForTest(pathlist)
List pathlist;
{
    LispValue x, y;
    Path path, path1;
    List path_prune_list = LispNil;
    List new_pathlist;

    foreach (x, pathlist) {
	path = (Path)CAR(x);
	if (pathShouldPruned(path, false))
	    path_prune_list = nappend1(path_prune_list, path);
      }
    new_pathlist = nset_difference(pathlist, path_prune_list);
    path_prune_list = LispNil;
    foreach (x, new_pathlist) {
	path = (Path)CAR(x);
	if (IsA(path,MergePath)) {
	    foreach (y, CDR(x)) {
		path1 = (Path)CAR(y);
		if (IsA(path1,MergePath) && 
		    equal(get_outerjoinpath(path), get_innerjoinpath(path1)) &&
		    equal(get_innerjoinpath(path), get_outerjoinpath(path1)))
		    path_prune_list = nappend1(path_prune_list, path1);
	      }
	  }
       }
    new_pathlist = nset_difference(new_pathlist, path_prune_list);
	    
    return new_pathlist;
}

bool
d405 2
a406 1
    if (IsA(p1,Temp) || IsA(p1,Hash))
d408 2
a409 1
    if (IsA(p2,Temp) || IsA(p2,Hash))
@


1.21
log
@more special-case code for my experiments only, will be got rid of
later. -- Wei
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.20 91/04/24 12:14:33 hong Exp Locker: hong $"); */
d34 1
d121 1
a121 1
	 qual = set_difference (qual,constant_qual);
d426 1
a426 1
    new_pathlist = set_difference(pathlist, path_prune_list);
d440 1
a440 1
    new_pathlist = set_difference(new_pathlist, path_prune_list);
d443 189
@


1.20
log
@added a special case for my experiments
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.19 90/12/27 19:20:05 sp Exp Locker: hong $"); */
d331 2
d337 3
a339 1
	  foreach (x, get_pathlist(final_relation)) {
d381 62
@


1.19
log
@Oper nodes now have a new field (opid) where the oid of the regproc
is stored (that used to be stored in 'opno' overriding the pg_operator
oid).
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.18 90/11/02 11:19:49 goh Exp Locker: sp $"); */
d35 1
d41 1
d328 17
a344 1
    if (final_relation)
d347 1
@


1.18
log
@ reverse the fix_opid change because it breaks
 since selectivities are computed from operator rather than
 function ids.  Bummer

maybe someday we'll fix it (again).

- jeff
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.16 90/09/25 16:36:41 kemnitz Exp $"); */
d90 9
@


1.17
log
@planner no longer fixes opids
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.16 90/08/14 11:40:12 cimarron Exp $"); */
a109 1
#ifdef PLANNER_FIX_OPIDS
a110 1
#endif
@


1.16
log
@Updating from revision 1.15 to revision 1.16
@
text
@d110 1
d112 1
@


1.15
log
@CreateNode(Foo) --> RMakeFoo() change
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.14 89/12/06 20:40:13 sp Exp $"); */
d17 9
d27 3
a29 6
#include "pg_lisp.h"
#include "parse.h"
#include "relation.h"
#include "relation.a.h"
#include "plannodes.h"
#include "plannodes.a.h"
a30 1
#include "planner/clause.h"
d32 1
a33 3
#include "planner/sortresult.h"
#include "planner/createplan.h"
#include "planner/allpaths.h"
@


1.14
log
@Call set_tlist_references() to modify the target list of a Result
node.
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.13 89/12/06 14:42:49 sp Exp Locker: sp $"); */
d32 5
d330 1
a330 3
    extern void PrintResult();
    extern bool EqualResult();
    Result node = New_Node(Result);
a343 2
    node->printFunc = PrintResult; 
    node->equalFunc = EqualResult;
@


1.13
log
@_query_result_relation_ is a LispValue, so we should call
CInteger() to get its actual value...
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.12 89/12/06 11:06:00 goh Exp $"); */
d215 5
a219 3
	  if ( constant_qual ) {
	    set_join_tlist_references ( plan ); 
	  }
@


1.12
log
@fixes the bug that spyros found about the "Gen"  scripts
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.11 89/12/04 11:40:16 goh Exp Locker: goh $"); */
d94 2
a95 1
					 (Index) _query_result_relation_,
@


1.11
log
@Hopefully the correct fix for constant qualifications.
Unfortunately, since the previous hack (using the outer-scan tuple)
didn't work, it appears that the executor will need major
fixing to execute "nested-dot" plans.

@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.10 89/12/03 20:09:49 sp Exp Locker: goh $"); */
d92 1
a92 1
		 return ((Plan)MakeSeqScan ((List) NULL, 
@


1.10
log
@Two bug fixes:
 1) Delete with constant quals (like "delete foo where 1 = 1 ") are
    now correctly planned (the planner used to generate a NULL plan)
 2) _query_result_relation_ is a LispValue, so we should first
    call CInteger before passing it as argument to  make_seqscan()
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.9 89/10/01 15:03:13 ong Exp $"); */
d201 1
d214 3
a216 1

@


1.9
log
@added resconstantqual as arg. to make_result()
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.8 89/09/05 17:17:55 mao C_Demo_1 $"); */
d131 1
d137 2
a138 1
					       _query_result_relation_,
@


1.8
log
@Working version of C-only demo
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.7 89/08/30 09:04:57 cimarron Exp $"); */
d200 4
a203 4
						     subtlist,
						     resttlist,
						     currentlevel,
						valid_sortkeys(sortkeys)),
d208 1
a208 1
				   constant_qual,
d312 1
a312 1
make_result( tlist,resrellevelqual,left,right)
d314 1
a314 1
     List resrellevelqual;
d330 1
a330 1
    set_resconstantqual(node, LispNil); 
@


1.7
log
@fixed make_result()
@
text
@d10 1
a10 1
/* RcsId ("$Header: RCS/planmain.c,v 1.6 89/08/23 16:04:13 ong Exp Locker: goh $"); */
@


1.6
log
@planner supports all but rules and mergesort
@
text
@d10 1
a10 1
/* RcsId ("$Header: /n/postgres/a/postgres/ong/postgres/src/planner/plan/RCS/planmain.c,v 1.5 89/08/04 14:30:04 goh Exp $"); */
d321 7
a327 6
    set_cost ((Plan)node,0.0);
    set_qptargetlist ((Plan)node, tlist);
    set_lefttree((Plan)node,left);
    set_righttree((Plan)node,right);
    set_resrellevelqual( node ,resrellevelqual); 
    set_resconstantqual( node ,LispNil); 
d329 4
@


1.5
log
@reorganised header files
@
text
@d10 1
a10 1
/* RcsId ("$Header: planmain.c,v 1.4 89/08/04 13:28:48 goh Locked $"); */
d134 1
a134 1
		   SeqScan scan = MakeSeqScan (tlist,
d270 3
a272 3
	_query_relation_list_ = LispNil;
	initialize_targetlist (flat_tlist);
	initialize_qualification (qual);
d274 1
a274 1

d279 8
a286 8
	initialize_join_clause_info (_query_relation_list_);
	_query_relation_list_ = find_paths (_query_relation_list_,
					    level,
					    sortkeys);
     if (_query_relation_list_)
       final_relation = (Rel)CAR (_query_relation_list_);
     else
       final_relation = (Rel)LispNil;
d294 1
a294 1
	  sort_relation_paths (get_pathlist (final_relation),
d296 2
a297 2
			       final_relation,
			       compute_targetlist_width(original_tlist));
d308 1
a308 1

d318 1
a318 1
    
d321 1
a321 2
    set_resrellevelqual( node ,resrellevelqual); 
    set_resconstantqual( node ,LispNil); 
d325 3
d329 1
@


1.4
log
@checkin for retrieve (x.all)
@
text
@d10 1
a10 1
/* RcsId ("$Header: planmain.c,v 1.3 89/08/01 14:36:16 goh Locked $"); */
d17 1
a17 1
#include "internal.h"
d24 7
a30 6
#include "clause.h"
#include "sortresult.h"
#include "tlist.h"
#include "sortresult.h"
#include "createplan.h"
#include "allpaths.h"
d32 1
a32 1
extern Result make_result();
d315 1
@


1.3
log
@retrieve (x=1) checkin
@
text
@d10 1
a10 1
/* RcsId ("$Header: planmain.c,v 1.2 89/07/21 12:37:02 goh Locked $"); */
a62 1
     /* XXX - prog form, maybe incorrect */
d67 3
a69 3
     Plan	subplan;
     List	subtlist;
     Plan 	restplan;
d72 1
a72 1
     Plan 	plan;
d283 1
a283 1
       final_relation = CAR (_query_relation_list_);
@


1.2
log
@phase 2-3 checkin
@
text
@d10 1
a10 1
/* RcsId ("$Header: planmain.c,v 1.1 89/07/18 15:16:51 goh Locked $"); */
d31 1
d92 1
a92 1
		 return ((Plan)make_seqscan ((List) NULL, 
d110 1
a110 1
}
d112 1
a112 1
/*    A query may have a non-variable target list and a non-variable */
d124 1
a124 1
	       return ((Plan)MakeResult (tlist,
d139 1
a139 1
		       return ((Plan)MakeResult (tlist,
d171 1
a171 1
       if ( !(equal (currentlevel,maxlevel))) {
d199 1
a199 1
	  plan = (Plan)MakeResult (new_result_tlist (tlist,
d222 2
a223 2
	 !(temp_p(subplan) || 
	   (seqscan_p(subplan) && 
d225 1
a225 1
	    temp_p (get_lefttree (subplan))))) {
d264 1
a264 1
     LispValue final_relation = LispNil;
d274 1
d283 4
a286 1
	final_relation = CAR (_query_relation_list_);
d300 8
d309 1
a309 2
     return (create_plan (get_cheapest_path (final_relation),
			  original_tlist));
d311 17
a327 1
}  /* function end  */
@


1.1
log
@Initial revision
@
text
@d10 1
a10 1
/* RcsId ("$Header: planmain.c,v 1.1 89/04/27 21:04:51 ong Locked $"); */
d14 1
a14 1
 *     		query_planner
d18 12
a30 8

extern LispValue subplanner();

#define DELETE  10
#define APPEND  11
#define RETRIEVE 12
#define REPLACE 13

d55 1
a55 1
LispValue
d57 4
a60 1
     LispValue command_type,tlist,qual,currentlevel,maxlevel ;
d66 7
a72 7
     LispValue level_tlist = LispNil;
     LispValue subplan = LispNil;
     LispValue subtlist = LispNil;
     LispValue restplan = LispNil;
     LispValue resttlist = LispNil;
     LispValue relation_level_clauses = LispNil;
     LispValue plan = LispNil;
d74 3
d84 1
a84 1

d86 24
a109 20
	  /* A command without a target list or qualification is an error, */
	  /* except for "delete foo". */
		
	  if (null (tlist) && null (qual)) {
	       if ( equal (command_type,DELETE) ) {
		    return (make_seqscan (LispNil,
					  LispNil,
					  _query_result_relation_,
					  LispNil));
	       } 
	       else
		 return(LispNil);
	  }
	  constant_qual = pull_constant_clauses (qual);
	  qual = set_difference (qual,constant_qual);
	  fix_opids (constant_qual);
	  sortkeys = relation_sortkeys (tlist);
	  flattened_tlist = flatten_tlist (tlist);
	  level_tlist = or (flattened_tlist,tlist);
     }
d111 1
a111 1
     /*    A query may have a non-variable target list and a non-variable */
d123 1
a123 1
	       return (make_result (tlist,
d133 14
a146 14
		    LispValue scan = make_seqscan (tlist,
						   LispNil,
						   _query_result_relation_,
						   LispNil);
		    if ( consp (constant_qual) ) {
			 return (make_result (tlist,
					      LispNil,
					      constant_qual,
					      scan,
					      LispNil));
		    } 
		    else {
			 return (scan);
		    } 
d149 1
a149 1

d151 1
a151 1
	       return(LispNil);
d191 3
a193 3
	  LispValue resttlist = LispNil;
	  LispValue subtlist = LispNil;
	  LispValue plan = LispNil;
d198 4
a201 4
	  plan = make_result (new_result_tlist (tlist,
						subtlist,
						resttlist,
						currentlevel,
d203 8
a210 7
			      new_result_qual(relation_level_clauses,
					      subtlist,
					      resttlist,
					      currentlevel),
			      constant_qual,
			      subplan,
			      restplan);
d259 1
a259 1
LispValue
@
