equalfuncs.c 19.0 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * equalfuncs.c
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *	  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.
 *
22
 *
B
Add:  
Bruce Momjian 已提交
23 24
 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
 * Portions Copyright (c) 1994, Regents of the University of California
25 26
 *
 * IDENTIFICATION
27
 *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.67 2000/06/29 07:35:56 tgl Exp $
28 29 30
 *
 *-------------------------------------------------------------------------
 */
31

32 33 34
#include "postgres.h"

#include "nodes/plannodes.h"
B
Bruce Momjian 已提交
35
#include "nodes/relation.h"
36 37
#include "utils/datum.h"

38
static bool equali(List *a, List *b);
39

40

41
/*
42
 *	Stuff from primnodes.h
43 44
 */

45
static bool
46
_equalResdom(Resdom *a, Resdom *b)
47
{
48
	if (a->resno != b->resno)
49
		return false;
50
	if (a->restype != b->restype)
51
		return false;
52
	if (a->restypmod != b->restypmod)
53
		return false;
54 55 56 57 58 59 60 61 62 63 64 65
	if (a->resname && b->resname)
	{
		if (strcmp(a->resname, b->resname) != 0)
			return false;
	}
	else
	{
		/* must both be null to be equal */
		if (a->resname != b->resname)
			return false;
	}
	if (a->ressortgroupref != b->ressortgroupref)
66
		return false;
67
	if (a->reskey != b->reskey)
68
		return false;
69
	if (a->reskeyop != b->reskeyop)
70
		return false;
71
	/* we ignore resjunk flag ... is this correct? */
72

73
	return true;
74 75
}

76
static bool
77
_equalFjoin(Fjoin *a, Fjoin *b)
78
{
79
	int			nNodes;
80 81

	if (a->fj_initialized != b->fj_initialized)
82
		return false;
83
	if (a->fj_nNodes != b->fj_nNodes)
84
		return false;
85
	if (!equal(a->fj_innerNode, b->fj_innerNode))
86
		return false;
87 88 89

	nNodes = a->fj_nNodes;
	if (memcmp(a->fj_results, b->fj_results, nNodes * sizeof(Datum)) != 0)
90
		return false;
91
	if (memcmp(a->fj_alwaysDone, b->fj_alwaysDone, nNodes * sizeof(bool)) != 0)
92
		return false;
93

94
	return true;
95 96
}

97
static bool
98
_equalExpr(Expr *a, Expr *b)
99
{
100 101 102 103 104

	/*
	 * We do not examine typeOid, since the optimizer often doesn't bother
	 * to set it in created nodes, and it is logically a derivative of the
	 * oper field anyway.
105
	 */
106
	if (a->opType != b->opType)
107
		return false;
108
	if (!equal(a->oper, b->oper))
109
		return false;
110
	if (!equal(a->args, b->args))
111
		return false;
112

113
	return true;
114 115
}

116 117 118
static bool
_equalAttr(Attr *a, Attr *b)
{
119
	if (strcmp(a->relname, b->relname) != 0)
120
		return false;
121
	if (!equal(a->attrs, b->attrs))
122 123
		return false;

124
	return true;
125 126
}

127
static bool
128
_equalVar(Var *a, Var *b)
129
{
130
	if (a->varno != b->varno)
131
		return false;
132
	if (a->varattno != b->varattno)
133
		return false;
134
	if (a->vartype != b->vartype)
135
		return false;
136
	if (a->vartypmod != b->vartypmod)
137
		return false;
138
	if (a->varlevelsup != b->varlevelsup)
139
		return false;
140
	if (a->varnoold != b->varnoold)
141
		return false;
142
	if (a->varoattno != b->varoattno)
143
		return false;
144

145
	return true;
146 147
}

148
static bool
149
_equalOper(Oper *a, Oper *b)
150
{
151
	if (a->opno != b->opno)
152
		return false;
153
	if (a->opresulttype != b->opresulttype)
154
		return false;
155 156 157

	/*
	 * We do not examine opid, opsize, or op_fcache, since these are
158 159 160 161 162
	 * logically derived from opno, and they may not be set yet depending
	 * on how far along the node is in the parse/plan pipeline.
	 *
	 * It's probably not really necessary to check opresulttype either...
	 */
163

164
	return true;
165 166
}

167
static bool
168
_equalConst(Const *a, Const *b)
169
{
170
	if (a->consttype != b->consttype)
171
		return false;
172
	if (a->constlen != b->constlen)
173
		return false;
174
	if (a->constisnull != b->constisnull)
175
		return false;
176
	if (a->constbyval != b->constbyval)
177
		return false;
178
	/* XXX What about constisset and constiscast? */
179

180
	/*
181 182 183
	 * We treat all NULL constants of the same type as equal. Someday this
	 * might need to change?  But datumIsEqual doesn't work on nulls,
	 * so...
184 185 186
	 */
	if (a->constisnull)
		return true;
187 188
	return (datumIsEqual(a->constvalue, b->constvalue,
						 a->consttype, a->constbyval, a->constlen));
189 190
}

191
static bool
192
_equalParam(Param *a, Param *b)
193
{
194
	if (a->paramkind != b->paramkind)
195
		return false;
196
	if (a->paramtype != b->paramtype)
197
		return false;
198
	if (!equal(a->param_tlist, b->param_tlist))
199
		return false;
200 201 202

	switch (a->paramkind)
	{
203 204 205 206
		case PARAM_NAMED:
		case PARAM_NEW:
		case PARAM_OLD:
			if (strcmp(a->paramname, b->paramname) != 0)
207
				return false;
208 209
			break;
		case PARAM_NUM:
V
Vadim B. Mikheev 已提交
210
		case PARAM_EXEC:
211
			if (a->paramid != b->paramid)
212
				return false;
213 214 215 216 217 218
			break;
		case PARAM_INVALID:

			/*
			 * XXX: Hmmm... What are we supposed to return in this case ??
			 */
219
			return true;
220 221
			break;
		default:
222
			elog(ERROR, "_equalParam: Invalid paramkind value: %d",
223
				 a->paramkind);
224 225
	}

226
	return true;
227 228
}

229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
static bool
_equalFunc(Func *a, Func *b)
{
	if (a->funcid != b->funcid)
		return false;
	if (a->functype != b->functype)
		return false;
	if (a->funcisindex != b->funcisindex)
		return false;
	if (a->funcsize != b->funcsize)
		return false;
	/* Note we do not look at func_fcache */
	if (!equal(a->func_tlist, b->func_tlist))
		return false;
	if (!equal(a->func_planlist, b->func_planlist))
		return false;

	return true;
}

249 250 251 252 253 254 255 256 257 258 259 260 261
static bool
_equalAggref(Aggref *a, Aggref *b)
{
	if (strcmp(a->aggname, b->aggname) != 0)
		return false;
	if (a->basetype != b->basetype)
		return false;
	if (a->aggtype != b->aggtype)
		return false;
	if (!equal(a->target, b->target))
		return false;
	if (a->usenulls != b->usenulls)
		return false;
262 263 264 265
	if (a->aggstar != b->aggstar)
		return false;
	if (a->aggdistinct != b->aggdistinct)
		return false;
266
	/* ignore aggno, which is only a private field for the executor */
267 268 269
	return true;
}

270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
static bool
_equalSubLink(SubLink *a, SubLink *b)
{
	if (a->subLinkType != b->subLinkType)
		return false;
	if (a->useor != b->useor)
		return false;
	if (!equal(a->lefthand, b->lefthand))
		return false;
	if (!equal(a->oper, b->oper))
		return false;
	if (!equal(a->subselect, b->subselect))
		return false;
	return true;
}

286 287 288 289 290 291 292 293 294 295 296 297
static bool
_equalRelabelType(RelabelType *a, RelabelType *b)
{
	if (!equal(a->arg, b->arg))
		return false;
	if (a->resulttype != b->resulttype)
		return false;
	if (a->resulttypmod != b->resulttypmod)
		return false;
	return true;
}

298
static bool
299
_equalArray(Array *a, Array *b)
300
{
301
	if (a->arrayelemtype != b->arrayelemtype)
302
		return false;
303 304
	/* We need not check arrayelemlength, arrayelembyval if types match */
	if (a->arrayndim != b->arrayndim)
305
		return false;
306 307
	/* XXX shouldn't we be checking all indices??? */
	if (a->arraylow.indx[0] != b->arraylow.indx[0])
308
		return false;
309
	if (a->arrayhigh.indx[0] != b->arrayhigh.indx[0])
310
		return false;
311
	if (a->arraylen != b->arraylen)
312
		return false;
313

314
	return true;
315 316
}

317
static bool
318
_equalArrayRef(ArrayRef *a, ArrayRef *b)
319
{
320
	if (a->refelemtype != b->refelemtype)
321
		return false;
322
	if (a->refattrlength != b->refattrlength)
323
		return false;
324
	if (a->refelemlength != b->refelemlength)
325
		return false;
326
	if (a->refelembyval != b->refelembyval)
327
		return false;
328 329 330 331 332 333 334
	if (!equal(a->refupperindexpr, b->refupperindexpr))
		return false;
	if (!equal(a->reflowerindexpr, b->reflowerindexpr))
		return false;
	if (!equal(a->refexpr, b->refexpr))
		return false;
	return equal(a->refassgnexpr, b->refassgnexpr);
335 336
}

B
Bruce Momjian 已提交
337
/*
338
 * Stuff from relation.h
B
Bruce Momjian 已提交
339
 */
340

B
Bruce Momjian 已提交
341
static bool
342
_equalRelOptInfo(RelOptInfo *a, RelOptInfo *b)
B
Bruce Momjian 已提交
343
{
344 345 346

	/*
	 * We treat RelOptInfos as equal if they refer to the same base rels
347 348
	 * joined in the same order.  Is this sufficient?
	 */
349
	return equali(a->relids, b->relids);
B
Bruce Momjian 已提交
350 351
}

352 353 354
static bool
_equalIndexOptInfo(IndexOptInfo *a, IndexOptInfo *b)
{
355 356 357 358

	/*
	 * We treat IndexOptInfos as equal if they refer to the same index. Is
	 * this sufficient?
359 360 361 362 363 364
	 */
	if (a->indexoid != b->indexoid)
		return false;
	return true;
}

365
static bool
366
_equalPathKeyItem(PathKeyItem *a, PathKeyItem *b)
367
{
368
	if (a->sortop != b->sortop)
369
		return false;
370
	if (!equal(a->key, b->key))
371 372
		return false;
	return true;
373 374
}

375
static bool
376
_equalPath(Path *a, Path *b)
377
{
378
	if (a->pathtype != b->pathtype)
379
		return false;
380
	if (!equal(a->parent, b->parent))
381
		return false;
382 383 384

	/*
	 * do not check path costs, since they may not be set yet, and being
385
	 * float values there are roundoff error issues anyway...
386
	 */
387
	if (!equal(a->pathkeys, b->pathkeys))
388 389
		return false;
	return true;
390 391
}

392
static bool
393
_equalIndexPath(IndexPath *a, IndexPath *b)
394
{
395
	if (!_equalPath((Path *) a, (Path *) b))
396
		return false;
397
	if (!equali(a->indexid, b->indexid))
398
		return false;
399
	if (!equal(a->indexqual, b->indexqual))
400
		return false;
401 402
	if (a->indexscandir != b->indexscandir)
		return false;
403 404
	if (!equali(a->joinrelids, b->joinrelids))
		return false;
405 406 407 408

	/*
	 * Skip 'rows' because of possibility of floating-point roundoff
	 * error. It should be derivable from the other fields anyway.
409
	 */
410
	return true;
411 412
}

413 414 415 416 417 418 419 420 421 422 423 424
static bool
_equalTidPath(TidPath *a, TidPath *b)
{
	if (!_equalPath((Path *) a, (Path *) b))
		return false;
	if (!equal(a->tideval, b->tideval))
		return false;
	if (!equali(a->unjoined_relids, b->unjoined_relids))
		return false;
	return true;
}

425
static bool
426
_equalJoinPath(JoinPath *a, JoinPath *b)
427
{
428
	if (!_equalPath((Path *) a, (Path *) b))
429
		return false;
430
	if (!equal(a->outerjoinpath, b->outerjoinpath))
431
		return false;
432
	if (!equal(a->innerjoinpath, b->innerjoinpath))
433
		return false;
434 435
	if (!equal(a->joinrestrictinfo, b->joinrestrictinfo))
		return false;
436
	return true;
437 438
}

439
static bool
440
_equalNestPath(NestPath *a, NestPath *b)
441
{
442
	if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
443 444
		return false;
	return true;
445 446
}

447
static bool
448
_equalMergePath(MergePath *a, MergePath *b)
449
{
450
	if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
451
		return false;
452
	if (!equal(a->path_mergeclauses, b->path_mergeclauses))
453
		return false;
454
	if (!equal(a->outersortkeys, b->outersortkeys))
455
		return false;
456
	if (!equal(a->innersortkeys, b->innersortkeys))
457 458
		return false;
	return true;
459 460
}

461
static bool
462
_equalHashPath(HashPath *a, HashPath *b)
463
{
464
	if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
465
		return false;
466
	if (!equal(a->path_hashclauses, b->path_hashclauses))
467 468
		return false;
	return true;
469 470
}

V
Vadim B. Mikheev 已提交
471 472 473
static bool
_equalSubPlan(SubPlan *a, SubPlan *b)
{
474
	/* should compare plans, but have to settle for comparing plan IDs */
V
Vadim B. Mikheev 已提交
475
	if (a->plan_id != b->plan_id)
476
		return false;
V
Vadim B. Mikheev 已提交
477

478 479 480
	if (!equal(a->rtable, b->rtable))
		return false;

481
	if (!equal(a->sublink, b->sublink))
482
		return false;
483

484
	return true;
V
Vadim B. Mikheev 已提交
485 486
}

487
static bool
488
_equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
489
{
490
	if (!equal(a->clause, b->clause))
491
		return false;
492
	if (!equal(a->subclauseindices, b->subclauseindices))
493
		return false;
494
	if (a->mergejoinoperator != b->mergejoinoperator)
495
		return false;
496 497 498 499 500
	if (a->left_sortop != b->left_sortop)
		return false;
	if (a->right_sortop != b->right_sortop)
		return false;
	if (a->hashjoinoperator != b->hashjoinoperator)
501 502
		return false;
	return true;
503 504
}

505
static bool
506
_equalJoinInfo(JoinInfo *a, JoinInfo *b)
507
{
508
	if (!equali(a->unjoined_relids, b->unjoined_relids))
509
		return false;
510
	if (!equal(a->jinfo_restrictinfo, b->jinfo_restrictinfo))
511
		return false;
512
	return true;
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
}

static bool
_equalIter(Iter *a, Iter *b)
{
	return equal(a->iterexpr, b->iterexpr);
}

static bool
_equalStream(Stream *a, Stream *b)
{
	if (a->clausetype != b->clausetype)
		return false;
	if (a->groupup != b->groupup)
		return false;
	if (a->groupcost != b->groupcost)
		return false;
	if (a->groupsel != b->groupsel)
		return false;
	if (!equal(a->pathptr, b->pathptr))
		return false;
	if (!equal(a->cinfo, b->cinfo))
		return false;
	if (!equal(a->upstream, b->upstream))
		return false;
	return equal(a->downstream, b->downstream);
}

541
/*
542
 *	Stuff from execnodes.h
543 544 545
 */

/*
546
 *	EState is a subclass of Node.
547
 */
548
static bool
549
_equalEState(EState *a, EState *b)
550
{
551
	if (a->es_direction != b->es_direction)
552
		return false;
553 554

	if (!equal(a->es_range_table, b->es_range_table))
555
		return false;
556 557

	if (a->es_result_relation_info != b->es_result_relation_info)
558
		return false;
559

560
	return true;
561 562
}

563 564 565 566 567 568 569 570 571 572 573 574 575
/*
 * Stuff from parsenodes.h
 */

static bool
_equalQuery(Query *a, Query *b)
{
	if (a->commandType != b->commandType)
		return false;
	if (!equal(a->utilityStmt, b->utilityStmt))
		return false;
	if (a->resultRelation != b->resultRelation)
		return false;
B
Bruce Momjian 已提交
576 577
	if (a->into && b->into)
	{
578 579
		if (strcmp(a->into, b->into) != 0)
			return false;
B
Bruce Momjian 已提交
580 581 582
	}
	else
	{
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597
		if (a->into != b->into)
			return false;
	}
	if (a->isPortal != b->isPortal)
		return false;
	if (a->isBinary != b->isBinary)
		return false;
	if (a->isTemp != b->isTemp)
		return false;
	if (a->unionall != b->unionall)
		return false;
	if (a->hasAggs != b->hasAggs)
		return false;
	if (a->hasSubLinks != b->hasSubLinks)
		return false;
598 599 600 601 602 603 604 605
	if (!equal(a->rtable, b->rtable))
		return false;
	if (!equal(a->targetList, b->targetList))
		return false;
	if (!equal(a->qual, b->qual))
		return false;
	if (!equal(a->rowMark, b->rowMark))
		return false;
606 607
	if (!equal(a->distinctClause, b->distinctClause))
		return false;
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
	if (!equal(a->sortClause, b->sortClause))
		return false;
	if (!equal(a->groupClause, b->groupClause))
		return false;
	if (!equal(a->havingQual, b->havingQual))
		return false;
	if (!equal(a->intersectClause, b->intersectClause))
		return false;
	if (!equal(a->unionClause, b->unionClause))
		return false;
	if (!equal(a->limitOffset, b->limitOffset))
		return false;
	if (!equal(a->limitCount, b->limitCount))
		return false;

B
Bruce Momjian 已提交
623
	/*
624
	 * We do not check the internal-to-the-planner fields: base_rel_list,
625 626 627
	 * join_rel_list, equi_key_list, query_pathkeys. They might not be set
	 * yet, and in any case they should be derivable from the other
	 * fields.
628 629 630 631 632 633 634
	 */
	return true;
}

static bool
_equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
{
B
Bruce Momjian 已提交
635 636
	if (a->relname && b->relname)
	{
637 638
		if (strcmp(a->relname, b->relname) != 0)
			return false;
B
Bruce Momjian 已提交
639 640 641
	}
	else
	{
642 643 644
		if (a->relname != b->relname)
			return false;
	}
645 646
	if (!equal(a->ref, b->ref))
		return false;
647 648 649 650 651 652
	if (a->relid != b->relid)
		return false;
	if (a->inh != b->inh)
		return false;
	if (a->inFromCl != b->inFromCl)
		return false;
653 654
	if (a->inJoinSet != b->inJoinSet)
		return false;
655 656 657 658 659 660
	if (a->skipAcl != b->skipAcl)
		return false;

	return true;
}

661 662 663 664 665 666 667 668 669 670 671
static bool
_equalSortClause(SortClause *a, SortClause *b)
{
	if (a->tleSortGroupRef != b->tleSortGroupRef)
		return false;
	if (a->sortop != b->sortop)
		return false;

	return true;
}

672 673 674 675 676 677 678 679 680 681 682
static bool
_equalRowMark(RowMark *a, RowMark *b)
{
	if (a->rti != b->rti)
		return false;
	if (a->info != b->info)
		return false;

	return true;
}

683
static bool
684
_equalTargetEntry(TargetEntry *a, TargetEntry *b)
685
{
686
	if (!equal(a->resdom, b->resdom))
687
		return false;
688
	if (!equal(a->fjoin, b->fjoin))
689
		return false;
690
	if (!equal(a->expr, b->expr))
691
		return false;
692

693
	return true;
694 695
}

696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
static bool
_equalCaseExpr(CaseExpr *a, CaseExpr *b)
{
	if (a->casetype != b->casetype)
		return false;
	if (!equal(a->arg, b->arg))
		return false;
	if (!equal(a->args, b->args))
		return false;
	if (!equal(a->defresult, b->defresult))
		return false;

	return true;
}

static bool
_equalCaseWhen(CaseWhen *a, CaseWhen *b)
{
	if (!equal(a->expr, b->expr))
		return false;
	if (!equal(a->result, b->result))
		return false;

	return true;
}

722
/*
723
 * Stuff from pg_list.h
724
 */
725

726
static bool
727
_equalValue(Value *a, Value *b)
728
{
729
	if (a->type != b->type)
730
		return false;
731 732 733

	switch (a->type)
	{
734
		case T_Integer:
735
			return a->val.ival == b->val.ival;
736
		case T_Float:
737 738
		case T_String:
			return strcmp(a->val.str, b->val.str) == 0;
739 740
		default:
			break;
741 742
	}

743
	return true;
744 745 746
}

/*
747
 * equal
748
 *	  returns whether two nodes are equal
749 750 751 752
 */
bool
equal(void *a, void *b)
{
753
	bool		retval = false;
754

755
	if (a == b)
756
		return true;
757 758 759 760 761

	/*
	 * note that a!=b, so only one of them can be NULL
	 */
	if (a == NULL || b == NULL)
762
		return false;
763 764 765 766 767

	/*
	 * are they the same type of nodes?
	 */
	if (nodeTag(a) != nodeTag(b))
768
		return false;
769 770 771

	switch (nodeTag(a))
	{
772 773 774
		case T_SubPlan:
			retval = _equalSubPlan(a, b);
			break;
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
		case T_Resdom:
			retval = _equalResdom(a, b);
			break;
		case T_Fjoin:
			retval = _equalFjoin(a, b);
			break;
		case T_Expr:
			retval = _equalExpr(a, b);
			break;
		case T_Var:
			retval = _equalVar(a, b);
			break;
		case T_Oper:
			retval = _equalOper(a, b);
			break;
		case T_Const:
			retval = _equalConst(a, b);
			break;
		case T_Param:
			retval = _equalParam(a, b);
			break;
796 797
		case T_Aggref:
			retval = _equalAggref(a, b);
798 799 800
			break;
		case T_SubLink:
			retval = _equalSubLink(a, b);
801
			break;
802 803 804
		case T_Func:
			retval = _equalFunc(a, b);
			break;
805 806
		case T_Array:
			retval = _equalArray(a, b);
807
			break;
808 809
		case T_ArrayRef:
			retval = _equalArrayRef(a, b);
B
Bruce Momjian 已提交
810
			break;
811 812
		case T_Iter:
			retval = _equalIter(a, b);
813
			break;
814 815 816 817 818
		case T_RelabelType:
			retval = _equalRelabelType(a, b);
			break;
		case T_RelOptInfo:
			retval = _equalRelOptInfo(a, b);
819 820 821 822 823 824 825
			break;
		case T_Path:
			retval = _equalPath(a, b);
			break;
		case T_IndexPath:
			retval = _equalIndexPath(a, b);
			break;
826 827
		case T_NestPath:
			retval = _equalNestPath(a, b);
828 829 830 831 832 833 834
			break;
		case T_MergePath:
			retval = _equalMergePath(a, b);
			break;
		case T_HashPath:
			retval = _equalHashPath(a, b);
			break;
835 836
		case T_PathKeyItem:
			retval = _equalPathKeyItem(a, b);
837
			break;
838 839
		case T_RestrictInfo:
			retval = _equalRestrictInfo(a, b);
V
Vadim B. Mikheev 已提交
840
			break;
841 842
		case T_JoinInfo:
			retval = _equalJoinInfo(a, b);
843
			break;
844 845 846 847 848 849 850 851 852
		case T_Stream:
			retval = _equalStream(a, b);
			break;
		case T_TidPath:
			retval = _equalTidPath(a, b);
			break;
		case T_IndexOptInfo:
			retval = _equalIndexOptInfo(a, b);
			break;
853 854 855
		case T_EState:
			retval = _equalEState(a, b);
			break;
856 857
		case T_Attr:
			retval = _equalAttr(a, b);
858 859
			break;
		case T_List:
860
			{
861 862 863 864
				List	   *la = (List *) a;
				List	   *lb = (List *) b;
				List	   *l;

865 866
				/*
				 * Try to reject by length check before we grovel through
867 868 869
				 * all the elements...
				 */
				if (length(la) != length(lb))
870
					return false;
871 872 873
				foreach(l, la)
				{
					if (!equal(lfirst(l), lfirst(lb)))
874
						return false;
875 876 877
					lb = lnext(lb);
				}
				retval = true;
878
			}
879
			break;
880 881 882 883 884
		case T_Integer:
		case T_Float:
		case T_String:
			retval = _equalValue(a, b);
			break;
885 886 887
		case T_Query:
			retval = _equalQuery(a, b);
			break;
888 889 890
		case T_TargetEntry:
			retval = _equalTargetEntry(a, b);
			break;
891 892 893
		case T_RangeTblEntry:
			retval = _equalRangeTblEntry(a, b);
			break;
894 895 896 897 898 899 900
		case T_SortClause:
			retval = _equalSortClause(a, b);
			break;
		case T_GroupClause:
			/* GroupClause is equivalent to SortClause */
			retval = _equalSortClause(a, b);
			break;
901 902 903 904 905 906
		case T_CaseExpr:
			retval = _equalCaseExpr(a, b);
			break;
		case T_CaseWhen:
			retval = _equalCaseWhen(a, b);
			break;
907 908 909 910
		case T_RowMark:
			retval = _equalRowMark(a, b);
			break;

911 912 913 914
		default:
			elog(NOTICE, "equal: don't know whether nodes of type %d are equal",
				 nodeTag(a));
			break;
915
	}
916 917

	return retval;
918 919 920
}

/*
921
 * equali
922
 *	  compares two lists of integers
923
 */
924
static bool
925
equali(List *a, List *b)
926
{
927
	List	   *l;
928

929
	foreach(l, a)
930
	{
931 932 933
		if (b == NIL)
			return false;
		if (lfirsti(l) != lfirsti(b))
934
			return false;
935
		b = lnext(b);
936
	}
937 938
	if (b != NIL)
		return false;
939
	return true;
940
}