/***********************************************************************
 ** *   Recursion Planner Header (recurplanner.h)                   * **
 ** *           Jimmy Bell                                          * **
 ** *                                                               * **
 ***********************************************************************
 *
 */

/* RcsId ("$Header: /usr/local/devel/postgres/src/backend/planner/RCS/recurplanner.h,v 1.5 1993/01/16 03:14:59 aoki Exp $"); */

#ifndef RecurPlannerIncluded
#define RecurPlannerIncluded

#include "tmp/c.h"				/* for String */

#include "executor/recursion_a.h"
#include "nodes/pg_lisp.h"
#include "parse.h"
#include "utils/rel.h"

#include "nodes/relation.h"
#include "nodes/relation.a.h"
#include "nodes/plannodes.h"
#include "nodes/plannodes.a.h"
#include "nodes/primnodes.a.h"
#include "executor/execdefs.h"
#include "executor/execmisc.h"

#include "planner/planner.h"
#include "planner/clauses.h"
#include "planner/var.h"
#include "planner/prepqual.h"
#include "planner/preptlist.h"

#include "executor/recursion.h"

/* *** JJJ - remove ? */
/* #include "xcxt.h"  --  for CID in executor */

/* extern Plan		planner();		/* in planner.c */
/* extern bool		null();			/* found in pg_lisp.h */
/* extern is_clause();
/* extern and_clause();
/* extern or_clause();
/* extern not_clause();
/* extern member();		/* for atom clause */

/* elsewhere ... JJJ - shouldn't need to be here */
extern
LispValue
append1 ARGS((
	LispValue	list,
	LispValue	lispObject
));

typedef List	Qualification;
typedef List	TargetList;
typedef List	QueryDescriptor;
typedef List	ParseTree;
typedef List	RangeTable;
typedef Relid	RelationId;		/* from relation.h */

#define ParseTreeGetRoot(parseTree) (List) parse_tree_root(parseTree)
#define ParseTreeGetNumLevels(parseTree) (List) \
	parse_tree_root_num_levels(parse_tree_root(parseTree))
#define ParseTreeGetCommandType(parseTree) (LispValue) \
	parse_tree_root_command_type(parse_tree_root(parseTree))
#define ParseTreeGetTargetList(parseTree) (TargetList) \
	parse_tree_target_list(parseTree)
#define ParseTreeGetQualification(parseTree) (Qualification) \
	parse_tree_qualification(parseTree)
#define ParseTreeGetResultRelation(parseTree) (List) \
	parse_tree_result_relation(parseTree)
#define ParseTreeGetRangeTable(parseTree) (List) \
	parse_tree_range_table(parseTree)



/* used to properly allocate space for a query string */
#define RELATION_NAME_LENGTH 16


/* Recursive Node containing query plan */

extern
Recursive
make_recursive ARGS((
	RecursiveMethod	recursiveMethod,
	Command		command,
	List		initPlans,
	List		loopPlans,
	List		cleanupPlans,
	List		checkpoints
));

/****
 *	functions to facilitate conversions between the internal
 *	form of plans and utility requests (like create FOO) and
 *	their list equivalents.
 */

/* either a utility request or a plan */

extern
GeneralPlan
PlanOrUtilityToGeneralPlan ARGS((
	bool		isUtility,
	PlanOrUtility	planOrUtility
));

/* List form of General Plan */
extern
List
GeneralPlanToList ARGS((
	GeneralPlan	generalPlan
));

/* General Plan extracted from List form */
extern
GeneralPlan
ListToGeneralPlan ARGS((
	List	list
));

/* containing utility request from string */
extern
GeneralPlan
StringToGeneralPlan ARGS((
	String		str
));

#define PlanToGeneralPlan(plan) PlanOrUtilityToGeneralPlan(false,plan)
#define UtilityToGeneralPlan(utilityRequest) \
	PlanOrUtilityToGeneralPlan(true,utilityRequest)

#define PlanToList(Plan) \
        GeneralPlanToList(PlanToGeneralPlan(Plan))
#define UtilityToList(utilityRequest) \
        GeneralPlanToList(UtilityToGeneralPlan(utilityRequest))
#define StringToList(utilityRequest) \
        GeneralPlanToList(StringToGeneralPlan(utilityRequest))

/*
 *	end of conversion functions
 *******
 */

/*******
 *	functions for checking linearity and verifying recursion
 */

/* name of result  relation */
extern
String
ParseTreeGetResultRelationName ARGS((
        ParseTree       parseTree
));

/*
 *	ParseTreeGetVariablesOnResultRelation --
 *		Take short-cut to approximate the number of tuple
 *		var's used to refer to result relation.  I count
 *		occurrences of result's name string in range table.
 */

/* number of tuple variables on result relation */
extern
int
ParseTreeGetVariablesOnResultRelation ARGS((
	ParseTree	parseTree
));

/*
 *	RecursiveQueryGetLinearity --
 *		Returns the number of distinct tuple variables in the
 *		query which reference the result relation.  If the user
 *		has not wasted tuple variables, this will be the level
 *		of recursion.  In delete and replace, a tuple variable
 *		is automatically declared for the result relation.
 *		Additional ones for any command are declared with the
 *		"from" clause.
 *
 *	Append* is only recursive if an assignment in the target list or
 *		part of the qualification is based a tuple variable of
 *		the result relation.  If the user references the result
 *		by name or declares tuple variables on it, assume recursive.
 *
 *	Retrieve* is similar.  We assume that the user has referenced
 *		the result relation by name, so if any additional
 *		tuple var's are declared for the result, we assume
 *		non-linearity.
 *
 *	Delete* is recursive only if an aggregate function or rule is
 *		used which is sensitive either to a decrease in the
 *		number of tuples, or to the absence of particular tuples.
 *		The not-in operator is also hole-sensitive.  If one of
 *		these 3 references the result relation, it should be
 *		assumed to be recursive (linear if exactly one tuple var).
 *		We assume that since one provided it is used this way.
 *		In the absence of not-in, this is not supported.
 *
 *	Replace* is assumed to be recursive since mere assignment from
 *		other relations based on a tuples field values can
 *		cause tuples to requalify on the nexxt iteration.  If
 *		additional tuple var's are declared, assumed nonlinear.
 *
 *	Execute* not supported at all.
 */

/* 0 if non-recursive, 1 if linear, 2+ if nonlinear */
extern
int
RecursiveQueryGetLinearity ARGS((
	ParseTree	parseTree
));

/*
 *	RecursiveMethodChoose -
 *		Determines which evaluation method to use on a recursive
 *		query.  Chooses between Naive and Seminaive based on a
 *		simplified linearity check.  Signals that the query is
 *		not recursive at all by returning RecursiveMethodNone,
 *		in which case the standard planner will take over.
 */

/* the optimal evaluation method to use */
extern
RecursiveMethod
RecursiveMethodChoose ARGS((
	ParseTree	parseTree
));

/* plan for recursive query, with recursion node at root */
extern
Plan
RecursiveQueryPlan ARGS((
	ParseTree	parseTree
));

#endif

