equalfuncs.c 16.7 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * equalfuncs.c
4
 *	  equality functions to compare node trees
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.49 1999/09/26 02:28:21 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
/*
25
 *	Stuff from primnodes.h
26 27
 */

28
static bool
29
_equalResdom(Resdom *a, Resdom *b)
30
{
31
	if (a->resno != b->resno)
32
		return false;
33
	if (a->restype != b->restype)
34
		return false;
35
	if (a->restypmod != b->restypmod)
36
		return false;
37 38 39 40 41 42 43 44 45 46 47 48
	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)
49
		return false;
50
	if (a->reskey != b->reskey)
51
		return false;
52
	if (a->reskeyop != b->reskeyop)
53
		return false;
54
	/* we ignore resjunk flag ... is this correct? */
55

56
	return true;
57 58
}

59
static bool
60
_equalFjoin(Fjoin *a, Fjoin *b)
61
{
62
	int			nNodes;
63 64

	if (a->fj_initialized != b->fj_initialized)
65
		return false;
66
	if (a->fj_nNodes != b->fj_nNodes)
67
		return false;
68
	if (!equal(a->fj_innerNode, b->fj_innerNode))
69
		return false;
70 71 72

	nNodes = a->fj_nNodes;
	if (memcmp(a->fj_results, b->fj_results, nNodes * sizeof(Datum)) != 0)
73
		return false;
74
	if (memcmp(a->fj_alwaysDone, b->fj_alwaysDone, nNodes * sizeof(bool)) != 0)
75
		return false;
76

77
	return true;
78 79
}

80
static bool
81
_equalExpr(Expr *a, Expr *b)
82
{
83 84 85 86
	/* 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.
	 */
87
	if (a->opType != b->opType)
88
		return false;
89
	if (!equal(a->oper, b->oper))
90
		return false;
91
	if (!equal(a->args, b->args))
92
		return false;
93

94
	return true;
95 96
}

97
static bool
98
_equalVar(Var *a, Var *b)
99
{
100
	if (a->varno != b->varno)
101
		return false;
102
	if (a->varattno != b->varattno)
103
		return false;
104
	if (a->vartype != b->vartype)
105
		return false;
106
	if (a->vartypmod != b->vartypmod)
107
		return false;
108
	if (a->varlevelsup != b->varlevelsup)
109
		return false;
110
	if (a->varnoold != b->varnoold)
111
		return false;
112
	if (a->varoattno != b->varoattno)
113
		return false;
114

115
	return true;
116 117
}

118
static bool
119
_equalOper(Oper *a, Oper *b)
120
{
121
	if (a->opno != b->opno)
122
		return false;
123
	if (a->opresulttype != b->opresulttype)
124
		return false;
125 126 127 128 129 130
	/* We do not examine opid, opsize, or op_fcache, since these are
	 * 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...
	 */
131

132
	return true;
133 134
}

135
static bool
136
_equalConst(Const *a, Const *b)
137
{
138
	if (a->consttype != b->consttype)
139
		return false;
140
	if (a->constlen != b->constlen)
141
		return false;
142
	if (a->constisnull != b->constisnull)
143
		return false;
144
	if (a->constbyval != b->constbyval)
145
		return false;
146
	/* XXX What about constisset and constiscast? */
147 148
	return (datumIsEqual(a->constvalue, b->constvalue,
						 a->consttype, a->constbyval, a->constlen));
149 150
}

151
static bool
152
_equalParam(Param *a, Param *b)
153
{
154
	if (a->paramkind != b->paramkind)
155
		return false;
156
	if (a->paramtype != b->paramtype)
157
		return false;
158
	if (!equal(a->param_tlist, b->param_tlist))
159
		return false;
160 161 162

	switch (a->paramkind)
	{
163 164 165 166
		case PARAM_NAMED:
		case PARAM_NEW:
		case PARAM_OLD:
			if (strcmp(a->paramname, b->paramname) != 0)
167
				return false;
168 169
			break;
		case PARAM_NUM:
V
Vadim B. Mikheev 已提交
170
		case PARAM_EXEC:
171
			if (a->paramid != b->paramid)
172
				return false;
173 174 175 176 177 178
			break;
		case PARAM_INVALID:

			/*
			 * XXX: Hmmm... What are we supposed to return in this case ??
			 */
179
			return true;
180 181
			break;
		default:
182
			elog(ERROR, "_equalParam: Invalid paramkind value: %d",
183
				 a->paramkind);
184 185
	}

186
	return true;
187 188
}

189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
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;
}

209 210 211 212 213 214 215 216 217 218 219 220 221
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;
222
	/* ignore aggno, which is only a private field for the executor */
223 224 225
	return true;
}

226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
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;
}

242
static bool
243
_equalArray(Array *a, Array *b)
244
{
245
	if (a->arrayelemtype != b->arrayelemtype)
246
		return false;
247 248
	/* We need not check arrayelemlength, arrayelembyval if types match */
	if (a->arrayndim != b->arrayndim)
249
		return false;
250 251
	/* XXX shouldn't we be checking all indices??? */
	if (a->arraylow.indx[0] != b->arraylow.indx[0])
252
		return false;
253
	if (a->arrayhigh.indx[0] != b->arrayhigh.indx[0])
254
		return false;
255
	if (a->arraylen != b->arraylen)
256
		return false;
257

258
	return true;
259 260
}

261
static bool
262
_equalArrayRef(ArrayRef *a, ArrayRef *b)
263
{
264
	if (a->refelemtype != b->refelemtype)
265
		return false;
266
	if (a->refattrlength != b->refattrlength)
267
		return false;
268
	if (a->refelemlength != b->refelemlength)
269
		return false;
270
	if (a->refelembyval != b->refelembyval)
271
		return false;
272 273 274 275 276 277 278
	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);
279 280
}

B
Bruce Momjian 已提交
281
/*
282
 * Stuff from relation.h
B
Bruce Momjian 已提交
283
 */
284

B
Bruce Momjian 已提交
285
static bool
286
_equalRelOptInfo(RelOptInfo *a, RelOptInfo *b)
B
Bruce Momjian 已提交
287
{
288 289 290
	/* We treat RelOptInfos as equal if they refer to the same base rels
	 * joined in the same order.  Is this sufficient?
	 */
291
	return equali(a->relids, b->relids);
B
Bruce Momjian 已提交
292 293
}

294
static bool
295
_equalPathKeyItem(PathKeyItem *a, PathKeyItem *b)
296
{
297
	if (a->sortop != b->sortop)
298
		return false;
299
	if (!equal(a->key, b->key))
300 301
		return false;
	return true;
302 303
}

304
static bool
305
_equalPath(Path *a, Path *b)
306
{
307
	if (a->pathtype != b->pathtype)
308
		return false;
309
	if (!equal(a->parent, b->parent))
310
		return false;
311 312
	/* do not check path_cost, since it may not be set yet, and being
	 * a float there are roundoff error issues anyway...
313
	 */
314
	if (!equal(a->pathkeys, b->pathkeys))
315 316
		return false;
	return true;
317 318
}

319
static bool
320
_equalIndexPath(IndexPath *a, IndexPath *b)
321
{
322
	if (!_equalPath((Path *) a, (Path *) b))
323
		return false;
324
	if (!equali(a->indexid, b->indexid))
325
		return false;
326
	if (!equal(a->indexqual, b->indexqual))
327
		return false;
328 329
	if (!equali(a->joinrelids, b->joinrelids))
		return false;
330
	return true;
331 332
}

333
static bool
334
_equalJoinPath(JoinPath *a, JoinPath *b)
335
{
336
	if (!_equalPath((Path *) a, (Path *) b))
337
		return false;
338
	if (!equal(a->pathinfo, b->pathinfo))
339
		return false;
340
	if (!equal(a->outerjoinpath, b->outerjoinpath))
341
		return false;
342
	if (!equal(a->innerjoinpath, b->innerjoinpath))
343 344
		return false;
	return true;
345 346
}

347
static bool
348
_equalNestPath(NestPath *a, NestPath *b)
349
{
350
	if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
351 352
		return false;
	return true;
353 354
}

355
static bool
356
_equalMergePath(MergePath *a, MergePath *b)
357
{
358
	if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
359
		return false;
360
	if (!equal(a->path_mergeclauses, b->path_mergeclauses))
361
		return false;
362
	if (!equal(a->outersortkeys, b->outersortkeys))
363
		return false;
364
	if (!equal(a->innersortkeys, b->innersortkeys))
365 366
		return false;
	return true;
367 368
}

369
static bool
370
_equalHashPath(HashPath *a, HashPath *b)
371
{
372
	if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
373
		return false;
374
	if (!equal(a->path_hashclauses, b->path_hashclauses))
375 376
		return false;
	return true;
377 378
}

379 380
/* XXX	This equality function is a quick hack, should be
 *		fixed to compare all fields.
381 382 383
 *
 * XXX  Why is this even here?  We don't have equal() funcs for
 *      any other kinds of Plan nodes... likely this is dead code...
384
 */
385
static bool
386
_equalIndexScan(IndexScan *a, IndexScan *b)
387
{
388 389 390 391
	/*
	 * if(a->scan.plan.cost != b->scan.plan.cost) return(false);
	 */

392
	if (!equal(a->indxqual, b->indxqual))
393
		return false;
394 395

	if (a->scan.scanrelid != b->scan.scanrelid)
396
		return false;
397

398 399 400
	if (a->indxorderdir != b->indxorderdir)
		return false;

401
	if (!equali(a->indxid, b->indxid))
402 403
		return false;
	return true;
404 405
}

V
Vadim B. Mikheev 已提交
406 407 408 409
static bool
_equalSubPlan(SubPlan *a, SubPlan *b)
{
	if (a->plan_id != b->plan_id)
410
		return false;
V
Vadim B. Mikheev 已提交
411

412
	if (!equal(a->sublink, b->sublink))
413
		return false;
414

415
	return true;
V
Vadim B. Mikheev 已提交
416 417
}

418
static bool
419
_equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
420
{
421
	if (!equal(a->clause, b->clause))
422
		return false;
423 424
	/* do not check selectivity because of roundoff error worries */
	if (!equal(a->subclauseindices, b->subclauseindices))
425
		return false;
426
	if (a->mergejoinoperator != b->mergejoinoperator)
427
		return false;
428 429 430 431 432
	if (a->left_sortop != b->left_sortop)
		return false;
	if (a->right_sortop != b->right_sortop)
		return false;
	if (a->hashjoinoperator != b->hashjoinoperator)
433 434
		return false;
	return true;
435 436
}

437
static bool
438
_equalJoinInfo(JoinInfo *a, JoinInfo *b)
439
{
440
	if (!equali(a->unjoined_relids, b->unjoined_relids))
441
		return false;
442
	if (!equal(a->jinfo_restrictinfo, b->jinfo_restrictinfo))
443
		return false;
444
	return true;
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
}

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);
}

473
/*
474
 *	Stuff from execnodes.h
475 476 477
 */

/*
478
 *	EState is a subclass of Node.
479
 */
480
static bool
481
_equalEState(EState *a, EState *b)
482
{
483
	if (a->es_direction != b->es_direction)
484
		return false;
485 486

	if (!equal(a->es_range_table, b->es_range_table))
487
		return false;
488 489

	if (a->es_result_relation_info != b->es_result_relation_info)
490
		return false;
491

492
	return true;
493 494
}

495 496 497 498 499 500 501 502 503 504 505 506 507
/*
 * 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 已提交
508 509
	if (a->into && b->into)
	{
510 511
		if (strcmp(a->into, b->into) != 0)
			return false;
B
Bruce Momjian 已提交
512 513 514
	}
	else
	{
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
		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;
530 531 532 533 534 535 536 537
	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;
B
Bruce Momjian 已提交
538 539
	if (a->uniqueFlag && b->uniqueFlag)
	{
540 541
		if (strcmp(a->uniqueFlag, b->uniqueFlag) != 0)
			return false;
B
Bruce Momjian 已提交
542 543 544
	}
	else
	{
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562
		if (a->uniqueFlag != b->uniqueFlag)
			return false;
	}
	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 已提交
563
	/*
564 565 566
	 * We do not check the internal-to-the-planner fields: base_rel_list,
	 * join_rel_list, query_pathkeys.  They might not be set yet, and
	 * in any case they should be derivable from the other fields.
567 568 569 570 571 572 573
	 */
	return true;
}

static bool
_equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
{
B
Bruce Momjian 已提交
574 575
	if (a->relname && b->relname)
	{
576 577
		if (strcmp(a->relname, b->relname) != 0)
			return false;
B
Bruce Momjian 已提交
578 579 580
	}
	else
	{
581 582 583
		if (a->relname != b->relname)
			return false;
	}
B
Bruce Momjian 已提交
584 585
	if (a->refname && b->refname)
	{
586 587
		if (strcmp(a->refname, b->refname) != 0)
			return false;
B
Bruce Momjian 已提交
588 589 590
	}
	else
	{
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
		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;
}

606
static bool
607
_equalTargetEntry(TargetEntry *a, TargetEntry *b)
608
{
609
	if (!equal(a->resdom, b->resdom))
610
		return false;
611
	if (!equal(a->fjoin, b->fjoin))
612
		return false;
613
	if (!equal(a->expr, b->expr))
614
		return false;
615

616
	return true;
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 643 644
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;
}

645
/*
646
 * Stuff from pg_list.h
647
 */
648

649
static bool
650
_equalValue(Value *a, Value *b)
651
{
652
	if (a->type != b->type)
653
		return false;
654 655 656

	switch (a->type)
	{
657 658 659
		case T_String:
			return strcmp(a->val.str, b->val.str);
		case T_Integer:
660
			return a->val.ival == b->val.ival;
661
		case T_Float:
662
			return a->val.dval == b->val.dval;
663 664
		default:
			break;
665 666
	}

667
	return true;
668 669 670
}

/*
671
 * equal
672
 *	  returns whether two nodes are equal
673 674 675 676
 */
bool
equal(void *a, void *b)
{
677
	bool		retval = false;
678

679
	if (a == b)
680
		return true;
681 682 683 684 685

	/*
	 * note that a!=b, so only one of them can be NULL
	 */
	if (a == NULL || b == NULL)
686
		return false;
687 688 689 690 691

	/*
	 * are they the same type of nodes?
	 */
	if (nodeTag(a) != nodeTag(b))
692
		return false;
693 694 695

	switch (nodeTag(a))
	{
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 722 723 724 725 726 727 728
		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;
729 730
		case T_Aggref:
			retval = _equalAggref(a, b);
731 732 733
			break;
		case T_SubLink:
			retval = _equalSubLink(a, b);
734
			break;
735 736 737
		case T_Func:
			retval = _equalFunc(a, b);
			break;
738 739
		case T_RestrictInfo:
			retval = _equalRestrictInfo(a, b);
740
			break;
B
Bruce Momjian 已提交
741 742 743
		case T_RelOptInfo:
			retval = _equalRelOptInfo(a, b);
			break;
744 745
		case T_PathKeyItem:
			retval = _equalPathKeyItem(a, b);
746 747 748 749 750 751 752
			break;
		case T_Path:
			retval = _equalPath(a, b);
			break;
		case T_IndexPath:
			retval = _equalIndexPath(a, b);
			break;
753 754
		case T_NestPath:
			retval = _equalNestPath(a, b);
755 756 757 758 759 760 761 762 763 764
			break;
		case T_MergePath:
			retval = _equalMergePath(a, b);
			break;
		case T_HashPath:
			retval = _equalHashPath(a, b);
			break;
		case T_IndexScan:
			retval = _equalIndexScan(a, b);
			break;
V
Vadim B. Mikheev 已提交
765 766 767
		case T_SubPlan:
			retval = _equalSubPlan(a, b);
			break;
768 769
		case T_JoinInfo:
			retval = _equalJoinInfo(a, b);
770 771 772 773 774 775 776 777 778 779
			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:
780
			{
781 782 783 784
				List	   *la = (List *) a;
				List	   *lb = (List *) b;
				List	   *l;

785 786 787 788
				/* Try to reject by length check before we grovel through
				 * all the elements...
				 */
				if (length(la) != length(lb))
789
					return false;
790 791 792
				foreach(l, la)
				{
					if (!equal(lfirst(l), lfirst(lb)))
793
						return false;
794 795 796
					lb = lnext(lb);
				}
				retval = true;
797
			}
798
			break;
799 800 801 802 803 804 805 806 807
		case T_Query:
			retval = _equalQuery(a, b);
			break;
		case T_RangeTblEntry:
			retval = _equalRangeTblEntry(a, b);
			break;
		case T_TargetEntry:
			retval = _equalTargetEntry(a, b);
			break;
808 809 810 811 812 813
		case T_CaseExpr:
			retval = _equalCaseExpr(a, b);
			break;
		case T_CaseWhen:
			retval = _equalCaseWhen(a, b);
			break;
814 815 816 817
		default:
			elog(NOTICE, "equal: don't know whether nodes of type %d are equal",
				 nodeTag(a));
			break;
818
	}
819 820

	return retval;
821 822 823
}

/*
824
 * equali
825
 *	  compares two lists of integers
826
 */
827
static bool
828
equali(List *a, List *b)
829
{
830
	List	   *l;
831

832
	foreach(l, a)
833
	{
834 835 836
		if (b == NIL)
			return false;
		if (lfirsti(l) != lfirsti(b))
837
			return false;
838
		b = lnext(b);
839
	}
840 841
	if (b != NIL)
		return false;
842
	return true;
843
}