equalfuncs.c 17.3 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * equalfuncs.c
4
 *	  equal functions to compare the nodes
5 6 7 8 9
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
10
 *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.44 1999/07/24 23:21:06 tgl Exp $
11 12 13
 *
 *-------------------------------------------------------------------------
 */
14

15 16 17
#include "postgres.h"

#include "nodes/plannodes.h"
B
Bruce Momjian 已提交
18
#include "nodes/relation.h"
19 20
#include "utils/datum.h"

21
static bool equali(List *a, List *b);
22

23
/*
24
 *	Stuff from primnodes.h
25 26 27
 */

/*
28
 *	Resdom is a subclass of Node.
29
 */
30
static bool
31
_equalResdom(Resdom *a, Resdom *b)
32
{
33
	if (a->resno != b->resno)
34
		return false;
35
	if (a->restype != b->restype)
36
		return false;
37
	if (a->restypmod != b->restypmod)
38
		return false;
39
	if (strcmp(a->resname, b->resname) != 0)
40
		return false;
41
	if (a->reskey != b->reskey)
42
		return false;
43 44
	if (a->resgroupref != b->resgroupref)
		return false;
45
	if (a->reskeyop != b->reskeyop)
46
		return false;
47

48
	return true;
49 50
}

51
static bool
52
_equalFjoin(Fjoin *a, Fjoin *b)
53
{
54
	int			nNodes;
55 56

	if (a->fj_initialized != b->fj_initialized)
57
		return false;
58
	if (a->fj_nNodes != b->fj_nNodes)
59
		return false;
60
	if (!equal(a->fj_innerNode, b->fj_innerNode))
61
		return false;
62 63 64

	nNodes = a->fj_nNodes;
	if (memcmp(a->fj_results, b->fj_results, nNodes * sizeof(Datum)) != 0)
65
		return false;
66
	if (memcmp(a->fj_alwaysDone, b->fj_alwaysDone, nNodes * sizeof(bool)) != 0)
67
		return false;
68

69
	return true;
70 71 72
}

/*
73
 *	Expr is a subclass of Node.
74
 */
75
static bool
76
_equalExpr(Expr *a, Expr *b)
77
{
78
	if (a->opType != b->opType)
79
		return false;
80
	if (!equal(a->oper, b->oper))
81
		return false;
82
	if (!equal(a->args, b->args))
83
		return false;
84

85
	return true;
86 87
}

88
static bool
89
_equalIter(Iter *a, Iter *b)
90
{
91
	return equal(a->iterexpr, b->iterexpr);
92 93
}

94
static bool
95
_equalStream(Stream *a, Stream *b)
96
{
97
	if (a->clausetype != b->clausetype)
98
		return false;
99
	if (a->groupup != b->groupup)
100
		return false;
101
	if (a->groupcost != b->groupcost)
102
		return false;
103
	if (a->groupsel != b->groupsel)
104
		return false;
105
	if (!equal(a->pathptr, b->pathptr))
106
		return false;
107
	if (!equal(a->cinfo, b->cinfo))
108
		return false;
109
	if (!equal(a->upstream, b->upstream))
110 111
		return false;
	return equal(a->downstream, b->downstream);
112 113 114
}

/*
115
 *	Var is a subclass of Expr.
116
 */
117
static bool
118
_equalVar(Var *a, Var *b)
119
{
120
	if (a->varno != b->varno)
121
		return false;
122
	if (a->varattno != b->varattno)
123
		return false;
124
	if (a->vartype != b->vartype)
125
		return false;
126
	if (a->vartypmod != b->vartypmod)
127
		return false;
128
	if (a->varlevelsup != b->varlevelsup)
129
		return false;
130
	if (a->varnoold != b->varnoold)
131
		return false;
132
	if (a->varoattno != b->varoattno)
133
		return false;
134

135
	return true;
136 137
}

138
static bool
B
Bruce Momjian 已提交
139
_equalArray(Array *a, Array *b)
140
{
141
	if (a->arrayelemtype != b->arrayelemtype)
142
		return false;
143
	if (a->arrayndim != b->arrayndim)
144
		return false;
145
	if (a->arraylow.indx[0] != b->arraylow.indx[0])
146
		return false;
147
	if (a->arrayhigh.indx[0] != b->arrayhigh.indx[0])
148
		return false;
149
	if (a->arraylen != b->arraylen)
150 151
		return false;
	return TRUE;
152 153
}

154
static bool
B
Bruce Momjian 已提交
155
_equalArrayRef(ArrayRef *a, ArrayRef *b)
156
{
157
	if (a->refelemtype != b->refelemtype)
158
		return false;
159
	if (a->refattrlength != b->refattrlength)
160
		return false;
161
	if (a->refelemlength != b->refelemlength)
162
		return false;
163
	if (a->refelembyval != b->refelembyval)
164
		return false;
165
	if (!equal(a->refupperindexpr, b->refupperindexpr))
166
		return false;
167
	if (!equal(a->reflowerindexpr, b->reflowerindexpr))
168
		return false;
169
	if (!equal(a->refexpr, b->refexpr))
170 171
		return false;
	return equal(a->refassgnexpr, b->refassgnexpr);
172 173 174
}

/*
175
 *	Oper is a subclass of Expr.
176
 */
177
static bool
178
_equalOper(Oper *a, Oper *b)
179
{
180
	if (a->opno != b->opno)
181
		return false;
182
	if (a->opresulttype != b->opresulttype)
183
		return false;
184

185
	return true;
186 187 188
}

/*
189
 *	Const is a subclass of Expr.
190
 */
191
static bool
192
_equalConst(Const *a, Const *b)
193
{
194 195 196 197 198 199

	/*
	 * * this function used to do a pointer compare on a and b.  That's *
	 * ridiculous.	-- JMH, 7/11/92
	 */
	if (a->consttype != b->consttype)
200
		return false;
201
	if (a->constlen != b->constlen)
202
		return false;
203
	if (a->constisnull != b->constisnull)
204
		return false;
205
	if (a->constbyval != b->constbyval)
206
		return false;
207 208
	return (datumIsEqual(a->constvalue, b->constvalue,
						 a->consttype, a->constbyval, a->constlen));
209 210 211
}

/*
212
 *	Param is a subclass of Expr.
213
 */
214
static bool
215
_equalParam(Param *a, Param *b)
216
{
217
	if (a->paramkind != b->paramkind)
218
		return false;
219
	if (a->paramtype != b->paramtype)
220
		return false;
221
	if (!equal(a->param_tlist, b->param_tlist))
222
		return false;
223 224 225

	switch (a->paramkind)
	{
226 227 228 229
		case PARAM_NAMED:
		case PARAM_NEW:
		case PARAM_OLD:
			if (strcmp(a->paramname, b->paramname) != 0)
230
				return false;
231 232
			break;
		case PARAM_NUM:
V
Vadim B. Mikheev 已提交
233
		case PARAM_EXEC:
234
			if (a->paramid != b->paramid)
235
				return false;
236 237 238 239 240 241
			break;
		case PARAM_INVALID:

			/*
			 * XXX: Hmmm... What are we supposed to return in this case ??
			 */
242
			return true;
243 244
			break;
		default:
245
			elog(ERROR, "_equalParam: Invalid paramkind value: %d",
246
				 a->paramkind);
247 248
	}

249
	return true;
250 251
}

252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
/*
 *	Aggref is a subclass of Expr.
 */
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->aggno != b->aggno)
		return false;
	if (a->usenulls != b->usenulls)
		return false;
	return true;
}

273
/*
274
 *	Func is a subclass of Expr.
275
 */
276
static bool
277
_equalFunc(Func *a, Func *b)
278
{
279
	if (a->funcid != b->funcid)
280
		return false;
281
	if (a->functype != b->functype)
282
		return false;
283
	if (a->funcisindex != b->funcisindex)
284
		return false;
285
	if (a->funcsize != b->funcsize)
286
		return false;
287
	if (!equal(a->func_tlist, b->func_tlist))
288
		return false;
289
	if (!equal(a->func_planlist, b->func_planlist))
290
		return false;
291

292
	return true;
293 294 295
}

/*
296
 * RestrictInfo is a subclass of Node.
297
 */
298
static bool
299
_equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
300
{
301 302
	Assert(IsA(a, RestrictInfo));
	Assert(IsA(b, RestrictInfo));
303 304

	if (!equal(a->clause, b->clause))
305
		return false;
306
	if (a->selectivity != b->selectivity)
307
		return false;
308
#ifdef EqualMergeOrderExists
309
	if (!EqualMergeOrder(a->mergejoinorder, b->mergejoinorder))
310
		return false;
311
#endif
312
	if (a->hashjoinoperator != b->hashjoinoperator)
313
		return false;
314
	return equal(a->indexids, b->indexids);
315 316
}

B
Bruce Momjian 已提交
317 318 319 320
/*
 * RelOptInfo is a subclass of Node.
 */
static bool
321
_equalRelOptInfo(RelOptInfo *a, RelOptInfo *b)
B
Bruce Momjian 已提交
322 323 324 325
{
	Assert(IsA(a, RelOptInfo));
	Assert(IsA(b, RelOptInfo));

326
	return equal(a->relids, b->relids);
B
Bruce Momjian 已提交
327 328
}

329
static bool
330
_equalJoinMethod(JoinMethod *a, JoinMethod *b)
331
{
332 333 334
	Assert(IsA(a, JoinMethod));
	Assert(IsA(b, JoinMethod));

335
	if (!equal(a->jmkeys, b->jmkeys))
336
		return false;
337
	if (!equal(a->clauses, b->clauses))
338 339
		return false;
	return true;
340 341
}

342
static bool
343
_equalPath(Path *a, Path *b)
344
{
345
	if (a->pathtype != b->pathtype)
346
		return false;
347
	if (a->parent != b->parent)
348
		return false;
349 350 351 352

	/*
	 * if (a->path_cost != b->path_cost) return(false);
	 */
B
Bruce Momjian 已提交
353
	if (a->pathorder->ordtype == SORTOP_ORDER)
354
	{
355
		int			i = 0;
356

B
Bruce Momjian 已提交
357 358
		if (a->pathorder->ord.sortop == NULL ||
			b->pathorder->ord.sortop == NULL)
359
		{
B
Bruce Momjian 已提交
360
			if (a->pathorder->ord.sortop != b->pathorder->ord.sortop)
361 362 363 364
				return false;
		}
		else
		{
B
Bruce Momjian 已提交
365 366
			while (a->pathorder->ord.sortop[i] != 0 &&
				   b->pathorder->ord.sortop[i] != 0)
367
			{
B
Bruce Momjian 已提交
368
				if (a->pathorder->ord.sortop[i] != b->pathorder->ord.sortop[i])
369 370 371
					return false;
				i++;
			}
B
Bruce Momjian 已提交
372 373
			if (a->pathorder->ord.sortop[i] != 0 ||
				b->pathorder->ord.sortop[i] != 0)
374 375 376 377 378
				return false;
		}
	}
	else
	{
B
Bruce Momjian 已提交
379
		if (!equal(a->pathorder->ord.merge, b->pathorder->ord.merge))
380
			return false;
381
	}
382
	if (!equal(a->pathkeys, b->pathkeys))
383
		return false;
384 385 386 387

	/*
	 * if (a->outerjoincost != b->outerjoincost) return(false);
	 */
388
	if (!equali(a->joinid, b->joinid))
389 390
		return false;
	return true;
391 392
}

393
static bool
394
_equalIndexPath(IndexPath *a, IndexPath *b)
395
{
396
	if (!_equalPath((Path *) a, (Path *) b))
397
		return false;
398
	if (!equali(a->indexid, b->indexid))
399
		return false;
400
	if (!equal(a->indexqual, b->indexqual))
401 402
		return false;
	return true;
403 404
}

405
static bool
406
_equalNestPath(NestPath *a, NestPath *b)
407
{
408 409 410 411
	Assert(IsA_JoinPath(a));
	Assert(IsA_JoinPath(b));

	if (!_equalPath((Path *) a, (Path *) b))
412
		return false;
413
	if (!equal(a->pathinfo, b->pathinfo))
414
		return false;
415
	if (!equal(a->outerjoinpath, b->outerjoinpath))
416
		return false;
417
	if (!equal(a->innerjoinpath, b->innerjoinpath))
418 419
		return false;
	return true;
420 421
}

422
static bool
423
_equalMergePath(MergePath *a, MergePath *b)
424
{
425 426 427
	Assert(IsA(a, MergePath));
	Assert(IsA(b, MergePath));

428
	if (!_equalNestPath((NestPath *) a, (NestPath *) b))
429
		return false;
B
Bruce Momjian 已提交
430
	if (!equal(a->path_mergeclauses, b->path_mergeclauses))
431
		return false;
B
Bruce Momjian 已提交
432
	if (!equal(a->outersortkeys, b->outersortkeys))
433
		return false;
B
Bruce Momjian 已提交
434
	if (!equal(a->innersortkeys, b->innersortkeys))
435 436
		return false;
	return true;
437 438
}

439
static bool
440
_equalHashPath(HashPath *a, HashPath *b)
441
{
442 443 444
	Assert(IsA(a, HashPath));
	Assert(IsA(b, HashPath));

445
	if (!_equalNestPath((NestPath *) a, (NestPath *) b))
446
		return false;
447
	if (!equal((a->path_hashclauses), (b->path_hashclauses)))
448
		return false;
449
	if (!equal(a->outerhashkeys, b->outerhashkeys))
450
		return false;
451
	if (!equal(a->innerhashkeys, b->innerhashkeys))
452 453
		return false;
	return true;
454 455
}

456
static bool
457
_equalJoinKey(JoinKey *a, JoinKey *b)
458
{
459 460 461
	Assert(IsA(a, JoinKey));
	Assert(IsA(b, JoinKey));

462
	if (!equal(a->outer, b->outer))
463
		return false;
464
	if (!equal(a->inner, b->inner))
465 466
		return false;
	return true;
467 468
}

469
static bool
470
_equalMergeOrder(MergeOrder *a, MergeOrder *b)
471
{
472
	if (a == (MergeOrder *) NULL && b == (MergeOrder *) NULL)
473
		return true;
474 475 476 477
	Assert(IsA(a, MergeOrder));
	Assert(IsA(b, MergeOrder));

	if (a->join_operator != b->join_operator)
478
		return false;
479
	if (a->left_operator != b->left_operator)
480
		return false;
481
	if (a->right_operator != b->right_operator)
482
		return false;
483
	if (a->left_type != b->left_type)
484
		return false;
485
	if (a->right_type != b->right_type)
486 487
		return false;
	return true;
488 489
}

490
static bool
491
_equalHashInfo(HashInfo *a, HashInfo *b)
492
{
493 494
	Assert(IsA(a, HashInfo));
	Assert(IsA(b, HashInfo));
495 496

	if (a->hashop != b->hashop)
497 498
		return false;
	return true;
499 500
}

501 502
/* XXX	This equality function is a quick hack, should be
 *		fixed to compare all fields.
503
 */
504
static bool
505
_equalIndexScan(IndexScan *a, IndexScan *b)
506
{
507 508 509 510 511 512 513
	Assert(IsA(a, IndexScan));
	Assert(IsA(b, IndexScan));

	/*
	 * if(a->scan.plan.cost != b->scan.plan.cost) return(false);
	 */

514
	if (!equal(a->indxqual, b->indxqual))
515
		return false;
516 517

	if (a->scan.scanrelid != b->scan.scanrelid)
518
		return false;
519

520
	if (!equali(a->indxid, b->indxid))
521 522
		return false;
	return true;
523 524
}

V
Vadim B. Mikheev 已提交
525 526 527 528
static bool
_equalSubPlan(SubPlan *a, SubPlan *b)
{
	if (a->plan_id != b->plan_id)
529
		return false;
V
Vadim B. Mikheev 已提交
530

531
	if (!equal(a->sublink->oper, b->sublink->oper))
532
		return false;
533

534
	return true;
V
Vadim B. Mikheev 已提交
535 536
}

537
static bool
538
_equalJoinInfo(JoinInfo *a, JoinInfo *b)
539
{
540 541
	Assert(IsA(a, JoinInfo));
	Assert(IsA(b, JoinInfo));
B
Bruce Momjian 已提交
542
	if (!equal(a->unjoined_relids, b->unjoined_relids))
543
		return false;
544
	if (!equal(a->jinfo_restrictinfo, b->jinfo_restrictinfo))
545
		return false;
546
	if (a->mergejoinable != b->mergejoinable)
547
		return false;
548
	if (a->hashjoinable != b->hashjoinable)
549 550
		return false;
	return true;
551 552 553
}

/*
554
 *	Stuff from execnodes.h
555 556 557
 */

/*
558
 *	EState is a subclass of Node.
559
 */
560
static bool
561
_equalEState(EState *a, EState *b)
562
{
563
	if (a->es_direction != b->es_direction)
564
		return false;
565 566

	if (!equal(a->es_range_table, b->es_range_table))
567
		return false;
568 569

	if (a->es_result_relation_info != b->es_result_relation_info)
570
		return false;
571

572
	return true;
573 574
}

575 576 577 578 579 580 581 582 583 584 585 586 587
/*
 * 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 已提交
588 589
	if (a->into && b->into)
	{
590 591
		if (strcmp(a->into, b->into) != 0)
			return false;
B
Bruce Momjian 已提交
592 593 594
	}
	else
	{
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
		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;
B
Bruce Momjian 已提交
610 611
	if (a->uniqueFlag && b->uniqueFlag)
	{
612 613
		if (strcmp(a->uniqueFlag, b->uniqueFlag) != 0)
			return false;
B
Bruce Momjian 已提交
614 615 616
	}
	else
	{
617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642
		if (a->uniqueFlag != b->uniqueFlag)
			return false;
	}
	if (!equal(a->sortClause, b->sortClause))
		return false;
	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;
	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 已提交
643 644 645 646
	/*
	 * We do not check the internal-to-the-planner fields base_rel_list
	 * and join_rel_list.  They might not be set yet, and in any case they
	 * should be derivable from the other fields.
647 648 649 650 651 652 653
	 */
	return true;
}

static bool
_equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
{
B
Bruce Momjian 已提交
654 655
	if (a->relname && b->relname)
	{
656 657
		if (strcmp(a->relname, b->relname) != 0)
			return false;
B
Bruce Momjian 已提交
658 659 660
	}
	else
	{
661 662 663
		if (a->relname != b->relname)
			return false;
	}
B
Bruce Momjian 已提交
664 665
	if (a->refname && b->refname)
	{
666 667
		if (strcmp(a->refname, b->refname) != 0)
			return false;
B
Bruce Momjian 已提交
668 669 670
	}
	else
	{
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
		if (a->refname != b->refname)
			return false;
	}
	if (a->relid != b->relid)
		return false;
	if (a->inh != b->inh)
		return false;
	if (a->inFromCl != b->inFromCl)
		return false;
	if (a->skipAcl != b->skipAcl)
		return false;

	return true;
}

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

696
	return true;
697 698
}

699
/*
700
 * Stuff from pg_list.h
701
 */
702

703
static bool
704
_equalValue(Value *a, Value *b)
705
{
706
	if (a->type != b->type)
707
		return false;
708 709 710

	switch (a->type)
	{
711 712 713
		case T_String:
			return strcmp(a->val.str, b->val.str);
		case T_Integer:
714
			return a->val.ival == b->val.ival;
715
		case T_Float:
716
			return a->val.dval == b->val.dval;
717 718
		default:
			break;
719 720
	}

721
	return true;
722 723 724
}

/*
725
 * equal
726
 *	  returns whether two nodes are equal
727 728 729 730
 */
bool
equal(void *a, void *b)
{
731
	bool		retval = false;
732

733
	if (a == b)
734
		return true;
735 736 737 738 739

	/*
	 * note that a!=b, so only one of them can be NULL
	 */
	if (a == NULL || b == NULL)
740
		return false;
741 742 743 744 745

	/*
	 * are they the same type of nodes?
	 */
	if (nodeTag(a) != nodeTag(b))
746
		return false;
747 748 749

	switch (nodeTag(a))
	{
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
		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_Iter:
			retval = _equalIter(a, b);
			break;
		case T_Stream:
			retval = _equalStream(a, b);
			break;
		case T_Var:
			retval = _equalVar(a, b);
			break;
		case T_Array:
			retval = _equalArray(a, b);
			break;
		case T_ArrayRef:
			retval = _equalArrayRef(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;
783 784 785
		case T_Aggref:
			retval = _equalAggref(a, b);
			break;
786 787 788
		case T_Func:
			retval = _equalFunc(a, b);
			break;
789 790
		case T_RestrictInfo:
			retval = _equalRestrictInfo(a, b);
791
			break;
B
Bruce Momjian 已提交
792 793 794
		case T_RelOptInfo:
			retval = _equalRelOptInfo(a, b);
			break;
795 796 797 798 799 800 801 802 803
		case T_JoinMethod:
			retval = _equalJoinMethod(a, b);
			break;
		case T_Path:
			retval = _equalPath(a, b);
			break;
		case T_IndexPath:
			retval = _equalIndexPath(a, b);
			break;
804 805
		case T_NestPath:
			retval = _equalNestPath(a, b);
806 807 808 809 810 811 812 813 814 815 816 817 818
			break;
		case T_MergePath:
			retval = _equalMergePath(a, b);
			break;
		case T_HashPath:
			retval = _equalHashPath(a, b);
			break;
		case T_JoinKey:
			retval = _equalJoinKey(a, b);
			break;
		case T_MergeOrder:
			retval = _equalMergeOrder(a, b);
			break;
819 820
		case T_HashInfo:
			retval = _equalHashInfo(a, b);
821 822 823 824
			break;
		case T_IndexScan:
			retval = _equalIndexScan(a, b);
			break;
V
Vadim B. Mikheev 已提交
825 826 827
		case T_SubPlan:
			retval = _equalSubPlan(a, b);
			break;
828 829
		case T_JoinInfo:
			retval = _equalJoinInfo(a, b);
830 831 832 833 834 835 836 837 838 839
			break;
		case T_EState:
			retval = _equalEState(a, b);
			break;
		case T_Integer:
		case T_String:
		case T_Float:
			retval = _equalValue(a, b);
			break;
		case T_List:
840
			{
841 842 843 844 845
				List	   *la = (List *) a;
				List	   *lb = (List *) b;
				List	   *l;

				if (a == NULL && b == NULL)
846
					return true;
847
				if (length(a) != length(b))
848
					return false;
849 850 851
				foreach(l, la)
				{
					if (!equal(lfirst(l), lfirst(lb)))
852
						return false;
853 854 855
					lb = lnext(lb);
				}
				retval = true;
856
			}
857
			break;
858 859 860 861 862 863 864 865 866
		case T_Query:
			retval = _equalQuery(a, b);
			break;
		case T_RangeTblEntry:
			retval = _equalRangeTblEntry(a, b);
			break;
		case T_TargetEntry:
			retval = _equalTargetEntry(a, b);
			break;
867 868 869 870
		default:
			elog(NOTICE, "equal: don't know whether nodes of type %d are equal",
				 nodeTag(a));
			break;
871
	}
872 873

	return retval;
874 875 876
}

/*
877
 * equali
878
 *	  compares two lists of integers
879 880 881
 *
 * XXX temp hack. needs something like T_IntList
 */
882
static bool
883
equali(List *a, List *b)
884
{
885 886 887
	List	   *la = (List *) a;
	List	   *lb = (List *) b;
	List	   *l;
888 889

	if (a == NULL && b == NULL)
890
		return true;
891
	if (length(a) != length(b))
892
		return false;
893 894 895
	foreach(l, la)
	{
		if (lfirsti(l) != lfirsti(lb))
896
			return false;
897 898 899
		lb = lnext(lb);
	}
	return true;
900
}