Commit 43ba1b44 authored by Tom Lane's avatar Tom Lane

Add test code to copy all parse/plan trees. Repair essential omissions

in copyfuncs and equalfuncs exposed by regression tests.  We still have
some work to do: these modules really ought to handle most or all of
the utility statement node types.  But it's better than it was.
parent 6a7b40d9
...@@ -3,12 +3,23 @@ ...@@ -3,12 +3,23 @@
* copyfuncs.c * copyfuncs.c
* Copy functions for Postgres tree nodes. * Copy functions for Postgres tree nodes.
* *
* NOTE: a general convention when copying or comparing plan nodes is
* that we ignore the executor state subnode. We do not need to look
* at it because no current uses of copyObject() or equal() need to
* deal with already-executing plan trees. By leaving the state subnodes
* out, we avoid needing to write copy/compare routines for all the
* different executor state node types.
*
* Another class of nodes not currently handled is nodes that appear
* only in "raw" parsetrees (gram.y output not yet analyzed by the parser).
* Perhaps some day that will need to be supported.
*
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
*
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.114 2000/06/18 22:44:05 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.115 2000/06/29 07:35:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1671,9 +1682,6 @@ copyObject(void *from) ...@@ -1671,9 +1682,6 @@ copyObject(void *from)
case T_Agg: case T_Agg:
retval = _copyAgg(from); retval = _copyAgg(from);
break; break;
case T_GroupClause:
retval = _copyGroupClause(from);
break;
case T_Unique: case T_Unique:
retval = _copyUnique(from); retval = _copyUnique(from);
break; break;
...@@ -1699,9 +1707,6 @@ copyObject(void *from) ...@@ -1699,9 +1707,6 @@ copyObject(void *from)
case T_Var: case T_Var:
retval = _copyVar(from); retval = _copyVar(from);
break; break;
case T_Attr:
retval = _copyAttr(from);
break;
case T_Oper: case T_Oper:
retval = _copyOper(from); retval = _copyOper(from);
break; break;
...@@ -1711,6 +1716,12 @@ copyObject(void *from) ...@@ -1711,6 +1716,12 @@ copyObject(void *from)
case T_Param: case T_Param:
retval = _copyParam(from); retval = _copyParam(from);
break; break;
case T_Aggref:
retval = _copyAggref(from);
break;
case T_SubLink:
retval = _copySubLink(from);
break;
case T_Func: case T_Func:
retval = _copyFunc(from); retval = _copyFunc(from);
break; break;
...@@ -1720,21 +1731,12 @@ copyObject(void *from) ...@@ -1720,21 +1731,12 @@ copyObject(void *from)
case T_ArrayRef: case T_ArrayRef:
retval = _copyArrayRef(from); retval = _copyArrayRef(from);
break; break;
case T_Aggref: case T_Iter:
retval = _copyAggref(from); retval = _copyIter(from);
break;
case T_SubLink:
retval = _copySubLink(from);
break; break;
case T_RelabelType: case T_RelabelType:
retval = _copyRelabelType(from); retval = _copyRelabelType(from);
break; break;
case T_CaseExpr:
retval = _copyCaseExpr(from);
break;
case T_CaseWhen:
retval = _copyCaseWhen(from);
break;
/* /*
* RELATION NODES * RELATION NODES
...@@ -1769,9 +1771,6 @@ copyObject(void *from) ...@@ -1769,9 +1771,6 @@ copyObject(void *from)
case T_JoinInfo: case T_JoinInfo:
retval = _copyJoinInfo(from); retval = _copyJoinInfo(from);
break; break;
case T_Iter:
retval = _copyIter(from);
break;
case T_Stream: case T_Stream:
retval = _copyStream(from); retval = _copyStream(from);
break; break;
...@@ -1780,29 +1779,35 @@ copyObject(void *from) ...@@ -1780,29 +1779,35 @@ copyObject(void *from)
break; break;
/* /*
* PARSE NODES * VALUE NODES
*/ */
case T_TargetEntry: case T_Integer:
retval = _copyTargetEntry(from); case T_Float:
break; case T_String:
case T_RangeTblEntry: retval = _copyValue(from);
retval = _copyRangeTblEntry(from);
break;
case T_RowMark:
retval = _copyRowMark(from);
break;
case T_SortClause:
retval = _copySortClause(from);
break;
case T_A_Const:
retval = _copyAConst(from);
break;
case T_TypeName:
retval = _copyTypeName(from);
break; break;
case T_TypeCast: case T_List:
retval = _copyTypeCast(from); {
List *list = from,
*l,
*nl;
/* rather ugly coding for speed... */
/* Note the input list cannot be NIL if we got here. */
nl = lcons(copyObject(lfirst(list)), NIL);
retval = nl;
foreach(l, lnext(list))
{
lnext(nl) = lcons(copyObject(lfirst(l)), NIL);
nl = lnext(nl);
}
}
break; break;
/*
* PARSE NODES
*/
case T_Query: case T_Query:
retval = _copyQuery(from); retval = _copyQuery(from);
break; break;
...@@ -1837,35 +1842,44 @@ copyObject(void *from) ...@@ -1837,35 +1842,44 @@ copyObject(void *from)
retval = _copyLockStmt(from); retval = _copyLockStmt(from);
break; break;
/* case T_Attr:
* VALUE NODES retval = _copyAttr(from);
*/
case T_Integer:
case T_Float:
case T_String:
retval = _copyValue(from);
break; break;
case T_List: case T_A_Const:
{ retval = _copyAConst(from);
List *list = from, break;
*l, case T_TypeCast:
*nl; retval = _copyTypeCast(from);
break;
/* rather ugly coding for speed... */ case T_TypeName:
/* Note the input list cannot be NIL if we got here. */ retval = _copyTypeName(from);
nl = lcons(copyObject(lfirst(list)), NIL); break;
retval = nl; case T_TargetEntry:
retval = _copyTargetEntry(from);
foreach(l, lnext(list)) break;
{ case T_RangeTblEntry:
lnext(nl) = lcons(copyObject(lfirst(l)), NIL); retval = _copyRangeTblEntry(from);
nl = lnext(nl);
}
}
break; break;
case T_SortClause:
retval = _copySortClause(from);
break;
case T_GroupClause:
retval = _copyGroupClause(from);
break;
case T_CaseExpr:
retval = _copyCaseExpr(from);
break;
case T_CaseWhen:
retval = _copyCaseWhen(from);
break;
case T_RowMark:
retval = _copyRowMark(from);
break;
default: default:
elog(ERROR, "copyObject: don't know how to copy %d", nodeTag(from)); elog(ERROR, "copyObject: don't know how to copy node type %d",
retval = from; nodeTag(from));
retval = from; /* keep compiler quiet */
break; break;
} }
return retval; return retval;
......
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* equalfuncs.c * equalfuncs.c
* equality functions to compare node trees * Equality functions to compare node trees.
*
* NOTE: a general convention when copying or comparing plan nodes is
* that we ignore the executor state subnode. We do not need to look
* at it because no current uses of copyObject() or equal() need to
* deal with already-executing plan trees. By leaving the state subnodes
* out, we avoid needing to write copy/compare routines for all the
* different executor state node types.
*
* Currently, in fact, equal() doesn't know how to compare Plan nodes
* at all, let alone their executor-state subnodes. This will probably
* need to be fixed someday, but presently there is no need to compare
* plan trees.
*
* Another class of nodes not currently handled is nodes that appear
* only in "raw" parsetrees (gram.y output not yet analyzed by the parser).
* Perhaps some day that will need to be supported.
*
* *
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
*
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.66 2000/04/12 17:15:16 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.67 2000/06/29 07:35:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -452,56 +468,6 @@ _equalHashPath(HashPath *a, HashPath *b) ...@@ -452,56 +468,6 @@ _equalHashPath(HashPath *a, HashPath *b)
return true; return true;
} }
/* XXX This equality function is a quick hack, should be
* fixed to compare all fields.
*
* XXX Why is this even here? We don't have equal() funcs for
* any other kinds of Plan nodes... likely this is dead code...
*/
static bool
_equalIndexScan(IndexScan *a, IndexScan *b)
{
/*
* if(a->scan.plan.cost != b->scan.plan.cost) return(false);
*/
if (!equal(a->indxqual, b->indxqual))
return false;
if (a->scan.scanrelid != b->scan.scanrelid)
return false;
if (a->indxorderdir != b->indxorderdir)
return false;
if (!equali(a->indxid, b->indxid))
return false;
return true;
}
static bool
_equalTidScan(TidScan *a, TidScan *b)
{
Assert(IsA(a, TidScan));
Assert(IsA(b, TidScan));
/*
* if(a->scan.plan.cost != b->scan.plan.cost) return(false);
*/
if (a->needRescan != b->needRescan)
return false;
if (!equal(a->tideval, b->tideval))
return false;
if (a->scan.scanrelid != b->scan.scanrelid)
return false;
return true;
}
static bool static bool
_equalSubPlan(SubPlan *a, SubPlan *b) _equalSubPlan(SubPlan *a, SubPlan *b)
{ {
...@@ -703,6 +669,17 @@ _equalSortClause(SortClause *a, SortClause *b) ...@@ -703,6 +669,17 @@ _equalSortClause(SortClause *a, SortClause *b)
return true; return true;
} }
static bool
_equalRowMark(RowMark *a, RowMark *b)
{
if (a->rti != b->rti)
return false;
if (a->info != b->info)
return false;
return true;
}
static bool static bool
_equalTargetEntry(TargetEntry *a, TargetEntry *b) _equalTargetEntry(TargetEntry *a, TargetEntry *b)
{ {
...@@ -792,6 +769,9 @@ equal(void *a, void *b) ...@@ -792,6 +769,9 @@ equal(void *a, void *b)
switch (nodeTag(a)) switch (nodeTag(a))
{ {
case T_SubPlan:
retval = _equalSubPlan(a, b);
break;
case T_Resdom: case T_Resdom:
retval = _equalResdom(a, b); retval = _equalResdom(a, b);
break; break;
...@@ -801,24 +781,9 @@ equal(void *a, void *b) ...@@ -801,24 +781,9 @@ equal(void *a, void *b)
case T_Expr: case T_Expr:
retval = _equalExpr(a, b); retval = _equalExpr(a, b);
break; break;
case T_Iter:
retval = _equalIter(a, b);
break;
case T_Stream:
retval = _equalStream(a, b);
break;
case T_Attr:
retval = _equalAttr(a, b);
break;
case T_Var: case T_Var:
retval = _equalVar(a, b); retval = _equalVar(a, b);
break; break;
case T_Array:
retval = _equalArray(a, b);
break;
case T_ArrayRef:
retval = _equalArrayRef(a, b);
break;
case T_Oper: case T_Oper:
retval = _equalOper(a, b); retval = _equalOper(a, b);
break; break;
...@@ -834,23 +799,23 @@ equal(void *a, void *b) ...@@ -834,23 +799,23 @@ equal(void *a, void *b)
case T_SubLink: case T_SubLink:
retval = _equalSubLink(a, b); retval = _equalSubLink(a, b);
break; break;
case T_RelabelType:
retval = _equalRelabelType(a, b);
break;
case T_Func: case T_Func:
retval = _equalFunc(a, b); retval = _equalFunc(a, b);
break; break;
case T_RestrictInfo: case T_Array:
retval = _equalRestrictInfo(a, b); retval = _equalArray(a, b);
break; break;
case T_RelOptInfo: case T_ArrayRef:
retval = _equalRelOptInfo(a, b); retval = _equalArrayRef(a, b);
break; break;
case T_IndexOptInfo: case T_Iter:
retval = _equalIndexOptInfo(a, b); retval = _equalIter(a, b);
break; break;
case T_PathKeyItem: case T_RelabelType:
retval = _equalPathKeyItem(a, b); retval = _equalRelabelType(a, b);
break;
case T_RelOptInfo:
retval = _equalRelOptInfo(a, b);
break; break;
case T_Path: case T_Path:
retval = _equalPath(a, b); retval = _equalPath(a, b);
...@@ -858,9 +823,6 @@ equal(void *a, void *b) ...@@ -858,9 +823,6 @@ equal(void *a, void *b)
case T_IndexPath: case T_IndexPath:
retval = _equalIndexPath(a, b); retval = _equalIndexPath(a, b);
break; break;
case T_TidPath:
retval = _equalTidPath(a, b);
break;
case T_NestPath: case T_NestPath:
retval = _equalNestPath(a, b); retval = _equalNestPath(a, b);
break; break;
...@@ -870,25 +832,29 @@ equal(void *a, void *b) ...@@ -870,25 +832,29 @@ equal(void *a, void *b)
case T_HashPath: case T_HashPath:
retval = _equalHashPath(a, b); retval = _equalHashPath(a, b);
break; break;
case T_IndexScan: case T_PathKeyItem:
retval = _equalIndexScan(a, b); retval = _equalPathKeyItem(a, b);
break;
case T_TidScan:
retval = _equalTidScan(a, b);
break; break;
case T_SubPlan: case T_RestrictInfo:
retval = _equalSubPlan(a, b); retval = _equalRestrictInfo(a, b);
break; break;
case T_JoinInfo: case T_JoinInfo:
retval = _equalJoinInfo(a, b); retval = _equalJoinInfo(a, b);
break; break;
case T_Stream:
retval = _equalStream(a, b);
break;
case T_TidPath:
retval = _equalTidPath(a, b);
break;
case T_IndexOptInfo:
retval = _equalIndexOptInfo(a, b);
break;
case T_EState: case T_EState:
retval = _equalEState(a, b); retval = _equalEState(a, b);
break; break;
case T_Integer: case T_Attr:
case T_Float: retval = _equalAttr(a, b);
case T_String:
retval = _equalValue(a, b);
break; break;
case T_List: case T_List:
{ {
...@@ -911,9 +877,17 @@ equal(void *a, void *b) ...@@ -911,9 +877,17 @@ equal(void *a, void *b)
retval = true; retval = true;
} }
break; break;
case T_Integer:
case T_Float:
case T_String:
retval = _equalValue(a, b);
break;
case T_Query: case T_Query:
retval = _equalQuery(a, b); retval = _equalQuery(a, b);
break; break;
case T_TargetEntry:
retval = _equalTargetEntry(a, b);
break;
case T_RangeTblEntry: case T_RangeTblEntry:
retval = _equalRangeTblEntry(a, b); retval = _equalRangeTblEntry(a, b);
break; break;
...@@ -924,15 +898,16 @@ equal(void *a, void *b) ...@@ -924,15 +898,16 @@ equal(void *a, void *b)
/* GroupClause is equivalent to SortClause */ /* GroupClause is equivalent to SortClause */
retval = _equalSortClause(a, b); retval = _equalSortClause(a, b);
break; break;
case T_TargetEntry:
retval = _equalTargetEntry(a, b);
break;
case T_CaseExpr: case T_CaseExpr:
retval = _equalCaseExpr(a, b); retval = _equalCaseExpr(a, b);
break; break;
case T_CaseWhen: case T_CaseWhen:
retval = _equalCaseWhen(a, b); retval = _equalCaseWhen(a, b);
break; break;
case T_RowMark:
retval = _equalRowMark(a, b);
break;
default: default:
elog(NOTICE, "equal: don't know whether nodes of type %d are equal", elog(NOTICE, "equal: don't know whether nodes of type %d are equal",
nodeTag(a)); nodeTag(a));
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.162 2000/06/28 03:32:18 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.163 2000/06/29 07:35:57 tgl Exp $
* *
* NOTES * NOTES
* this is the "main" module of the postgres backend and * this is the "main" module of the postgres backend and
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h"
#include <unistd.h> #include <unistd.h>
#include <signal.h> #include <signal.h>
#include <time.h> #include <time.h>
...@@ -24,9 +26,6 @@ ...@@ -24,9 +26,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/socket.h> #include <sys/socket.h>
#include "postgres.h"
#include <errno.h> #include <errno.h>
#if HAVE_SYS_SELECT_H #if HAVE_SYS_SELECT_H
#include <sys/select.h> #include <sys/select.h>
...@@ -408,6 +407,31 @@ pg_parse_and_rewrite(char *query_string, /* string to execute */ ...@@ -408,6 +407,31 @@ pg_parse_and_rewrite(char *query_string, /* string to execute */
querytree_list = new_list; querytree_list = new_list;
#ifdef COPY_PARSE_PLAN_TREES
/* Optional debugging check: pass parsetree output through copyObject() */
/*
* Note: we run this test after rewrite, not before, because copyObject()
* does not handle most kinds of nodes that are used only in raw parse
* trees. The present (bizarre) implementation of UNION/INTERSECT/EXCEPT
* doesn't run analysis of the second and later subqueries until rewrite,
* so we'd get false failures on these queries if we did it beforehand.
*
* Currently, copyObject doesn't know about most of the utility query
* types, so suppress the check until that can be fixed... it should
* be fixed, though.
*/
if (querytree_list &&
((Query *) lfirst(querytree_list))->commandType != CMD_UTILITY)
{
new_list = (List *) copyObject(querytree_list);
/* This checks both copyObject() and the equal() routines... */
if (! equal(new_list, querytree_list))
elog(NOTICE, "pg_parse_and_rewrite: copyObject failed on parse tree");
else
querytree_list = new_list;
}
#endif
if (Debug_print_rewritten) if (Debug_print_rewritten)
{ {
if (Debug_pretty_print) if (Debug_pretty_print)
...@@ -458,6 +482,24 @@ pg_plan_query(Query *querytree) ...@@ -458,6 +482,24 @@ pg_plan_query(Query *querytree)
ShowUsage(); ShowUsage();
} }
#ifdef COPY_PARSE_PLAN_TREES
/* Optional debugging check: pass plan output through copyObject() */
{
Plan *new_plan = (Plan *) copyObject(plan);
/* equal() currently does not have routines to compare Plan nodes,
* so don't try to test equality here. Perhaps fix someday?
*/
#ifdef NOT_USED
/* This checks both copyObject() and the equal() routines... */
if (! equal(new_plan, plan))
elog(NOTICE, "pg_plan_query: copyObject failed on plan tree");
else
#endif
plan = new_plan;
}
#endif
/* ---------------- /* ----------------
* Print plan if debugging. * Print plan if debugging.
* ---------------- * ----------------
...@@ -1366,7 +1408,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) ...@@ -1366,7 +1408,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
if (!IsUnderPostmaster) if (!IsUnderPostmaster)
{ {
puts("\nPOSTGRES backend interactive interface "); puts("\nPOSTGRES backend interactive interface ");
puts("$Revision: 1.162 $ $Date: 2000/06/28 03:32:18 $\n"); puts("$Revision: 1.163 $ $Date: 2000/06/29 07:35:57 $\n");
} }
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment