equalfuncs.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:18k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * equalfuncs.c
  4.  *   equal functions to compare the nodes
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.39.2.1 1999/07/29 03:34:11 tgl Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include <string.h>
  15. #include "postgres.h"
  16. #include "nodes/nodes.h"
  17. #include "nodes/primnodes.h"
  18. #include "nodes/relation.h"
  19. #include "nodes/execnodes.h"
  20. #include "nodes/plannodes.h"
  21. #include "utils/builtins.h" /* for namestrcmp() */
  22. #include "utils/datum.h"
  23. #include "utils/elog.h"
  24. #include "storage/itemptr.h"
  25. static bool equali(List *a, List *b);
  26. /*
  27.  * Stuff from primnodes.h
  28.  */
  29. /*
  30.  * Resdom is a subclass of Node.
  31.  */
  32. static bool
  33. _equalResdom(Resdom *a, Resdom *b)
  34. {
  35. if (a->resno != b->resno)
  36. return false;
  37. if (a->restype != b->restype)
  38. return false;
  39. if (a->restypmod != b->restypmod)
  40. return false;
  41. if (strcmp(a->resname, b->resname) != 0)
  42. return false;
  43. if (a->reskey != b->reskey)
  44. return false;
  45. if (a->resgroupref != b->resgroupref)
  46. return false;
  47. if (a->reskeyop != b->reskeyop)
  48. return false;
  49. return true;
  50. }
  51. static bool
  52. _equalFjoin(Fjoin *a, Fjoin *b)
  53. {
  54. int nNodes;
  55. if (a->fj_initialized != b->fj_initialized)
  56. return false;
  57. if (a->fj_nNodes != b->fj_nNodes)
  58. return false;
  59. if (!equal(a->fj_innerNode, b->fj_innerNode))
  60. return false;
  61. nNodes = a->fj_nNodes;
  62. if (memcmp(a->fj_results, b->fj_results, nNodes * sizeof(Datum)) != 0)
  63. return false;
  64. if (memcmp(a->fj_alwaysDone, b->fj_alwaysDone, nNodes * sizeof(bool)) != 0)
  65. return false;
  66. return true;
  67. }
  68. /*
  69.  * Expr is a subclass of Node.
  70.  */
  71. static bool
  72. _equalExpr(Expr *a, Expr *b)
  73. {
  74. if (a->opType != b->opType)
  75. return false;
  76. if (!equal(a->oper, b->oper))
  77. return false;
  78. if (!equal(a->args, b->args))
  79. return false;
  80. return true;
  81. }
  82. static bool
  83. _equalIter(Iter *a, Iter *b)
  84. {
  85. return equal(a->iterexpr, b->iterexpr);
  86. }
  87. static bool
  88. _equalStream(Stream *a, Stream *b)
  89. {
  90. if (a->clausetype != b->clausetype)
  91. return false;
  92. if (a->groupup != b->groupup)
  93. return false;
  94. if (a->groupcost != b->groupcost)
  95. return false;
  96. if (a->groupsel != b->groupsel)
  97. return false;
  98. if (!equal(a->pathptr, b->pathptr))
  99. return false;
  100. if (!equal(a->cinfo, b->cinfo))
  101. return false;
  102. if (!equal(a->upstream, b->upstream))
  103. return false;
  104. return equal(a->downstream, b->downstream);
  105. }
  106. /*
  107.  * Var is a subclass of Expr.
  108.  */
  109. static bool
  110. _equalVar(Var *a, Var *b)
  111. {
  112. if (a->varno != b->varno)
  113. return false;
  114. if (a->varattno != b->varattno)
  115. return false;
  116. if (a->vartype != b->vartype)
  117. return false;
  118. if (a->vartypmod != b->vartypmod)
  119. return false;
  120. if (a->varlevelsup != b->varlevelsup)
  121. return false;
  122. if (a->varnoold != b->varnoold)
  123. return false;
  124. if (a->varoattno != b->varoattno)
  125. return false;
  126. return true;
  127. }
  128. static bool
  129. _equalArray(Array *a, Array *b)
  130. {
  131. if (a->arrayelemtype != b->arrayelemtype)
  132. return false;
  133. if (a->arrayndim != b->arrayndim)
  134. return false;
  135. if (a->arraylow.indx[0] != b->arraylow.indx[0])
  136. return false;
  137. if (a->arrayhigh.indx[0] != b->arrayhigh.indx[0])
  138. return false;
  139. if (a->arraylen != b->arraylen)
  140. return false;
  141. return TRUE;
  142. }
  143. static bool
  144. _equalArrayRef(ArrayRef *a, ArrayRef *b)
  145. {
  146. if (a->refelemtype != b->refelemtype)
  147. return false;
  148. if (a->refattrlength != b->refattrlength)
  149. return false;
  150. if (a->refelemlength != b->refelemlength)
  151. return false;
  152. if (a->refelembyval != b->refelembyval)
  153. return false;
  154. if (!equal(a->refupperindexpr, b->refupperindexpr))
  155. return false;
  156. if (!equal(a->reflowerindexpr, b->reflowerindexpr))
  157. return false;
  158. if (!equal(a->refexpr, b->refexpr))
  159. return false;
  160. return equal(a->refassgnexpr, b->refassgnexpr);
  161. }
  162. /*
  163.  * Oper is a subclass of Expr.
  164.  */
  165. static bool
  166. _equalOper(Oper *a, Oper *b)
  167. {
  168. if (a->opno != b->opno)
  169. return false;
  170. if (a->opresulttype != b->opresulttype)
  171. return false;
  172. return true;
  173. }
  174. /*
  175.  * Const is a subclass of Expr.
  176.  */
  177. static bool
  178. _equalConst(Const *a, Const *b)
  179. {
  180. /*
  181.  * * this function used to do a pointer compare on a and b.  That's *
  182.  * ridiculous. -- JMH, 7/11/92
  183.  */
  184. if (a->consttype != b->consttype)
  185. return false;
  186. if (a->constlen != b->constlen)
  187. return false;
  188. if (a->constisnull != b->constisnull)
  189. return false;
  190. if (a->constbyval != b->constbyval)
  191. return false;
  192. return (datumIsEqual(a->constvalue, b->constvalue,
  193.  a->consttype, a->constbyval, a->constlen));
  194. }
  195. /*
  196.  * Param is a subclass of Expr.
  197.  */
  198. static bool
  199. _equalParam(Param *a, Param *b)
  200. {
  201. if (a->paramkind != b->paramkind)
  202. return false;
  203. if (a->paramtype != b->paramtype)
  204. return false;
  205. if (!equal(a->param_tlist, b->param_tlist))
  206. return false;
  207. switch (a->paramkind)
  208. {
  209. case PARAM_NAMED:
  210. case PARAM_NEW:
  211. case PARAM_OLD:
  212. if (strcmp(a->paramname, b->paramname) != 0)
  213. return false;
  214. break;
  215. case PARAM_NUM:
  216. case PARAM_EXEC:
  217. if (a->paramid != b->paramid)
  218. return false;
  219. break;
  220. case PARAM_INVALID:
  221. /*
  222.  * XXX: Hmmm... What are we supposed to return in this case ??
  223.  */
  224. return true;
  225. break;
  226. default:
  227. elog(ERROR, "_equalParam: Invalid paramkind value: %d",
  228.  a->paramkind);
  229. }
  230. return true;
  231. }
  232. /*
  233.  * Aggref is a subclass of Expr.
  234.  */
  235. static bool
  236. _equalAggref(Aggref *a, Aggref *b)
  237. {
  238. if (strcmp(a->aggname, b->aggname) != 0)
  239. return false;
  240. if (a->basetype != b->basetype)
  241. return false;
  242. if (a->aggtype != b->aggtype)
  243. return false;
  244. if (!equal(a->target, b->target))
  245. return false;
  246. if (a->aggno != b->aggno)
  247. return false;
  248. if (a->usenulls != b->usenulls)
  249. return false;
  250. return true;
  251. }
  252. /*
  253.  * Func is a subclass of Expr.
  254.  */
  255. static bool
  256. _equalFunc(Func *a, Func *b)
  257. {
  258. if (a->funcid != b->funcid)
  259. return false;
  260. if (a->functype != b->functype)
  261. return false;
  262. if (a->funcisindex != b->funcisindex)
  263. return false;
  264. if (a->funcsize != b->funcsize)
  265. return false;
  266. if (!equal(a->func_tlist, b->func_tlist))
  267. return false;
  268. if (!equal(a->func_planlist, b->func_planlist))
  269. return false;
  270. return true;
  271. }
  272. /*
  273.  * RestrictInfo is a subclass of Node.
  274.  */
  275. static bool
  276. _equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
  277. {
  278. Assert(IsA(a, RestrictInfo));
  279. Assert(IsA(b, RestrictInfo));
  280. if (!equal(a->clause, b->clause))
  281. return false;
  282. if (a->selectivity != b->selectivity)
  283. return false;
  284. if (a->notclause != b->notclause)
  285. return false;
  286. #ifdef EqualMergeOrderExists
  287. if (!EqualMergeOrder(a->mergejoinorder, b->mergejoinorder))
  288. return false;
  289. #endif
  290. if (a->hashjoinoperator != b->hashjoinoperator)
  291. return false;
  292. return equal(a->indexids, b->indexids);
  293. }
  294. /*
  295.  * RelOptInfo is a subclass of Node.
  296.  */
  297. static bool
  298. _equalRelOptInfo(RelOptInfo *a, RelOptInfo *b)
  299. {
  300. Assert(IsA(a, RelOptInfo));
  301. Assert(IsA(b, RelOptInfo));
  302. return equal(a->relids, b->relids);
  303. }
  304. static bool
  305. _equalJoinMethod(JoinMethod *a, JoinMethod *b)
  306. {
  307. Assert(IsA(a, JoinMethod));
  308. Assert(IsA(b, JoinMethod));
  309. if (!equal(a->jmkeys, b->jmkeys))
  310. return false;
  311. if (!equal(a->clauses, b->clauses))
  312. return false;
  313. return true;
  314. }
  315. static bool
  316. _equalPath(Path *a, Path *b)
  317. {
  318. if (a->pathtype != b->pathtype)
  319. return false;
  320. if (a->parent != b->parent)
  321. return false;
  322. /*
  323.  * if (a->path_cost != b->path_cost) return(false);
  324.  */
  325. if (a->pathorder->ordtype == SORTOP_ORDER)
  326. {
  327. int i = 0;
  328. if (a->pathorder->ord.sortop == NULL ||
  329. b->pathorder->ord.sortop == NULL)
  330. {
  331. if (a->pathorder->ord.sortop != b->pathorder->ord.sortop)
  332. return false;
  333. }
  334. else
  335. {
  336. while (a->pathorder->ord.sortop[i] != 0 &&
  337.    b->pathorder->ord.sortop[i] != 0)
  338. {
  339. if (a->pathorder->ord.sortop[i] != b->pathorder->ord.sortop[i])
  340. return false;
  341. i++;
  342. }
  343. if (a->pathorder->ord.sortop[i] != 0 ||
  344. b->pathorder->ord.sortop[i] != 0)
  345. return false;
  346. }
  347. }
  348. else
  349. {
  350. if (!equal(a->pathorder->ord.merge, b->pathorder->ord.merge))
  351. return false;
  352. }
  353. if (!equal(a->pathkeys, b->pathkeys))
  354. return false;
  355. /*
  356.  * if (a->outerjoincost != b->outerjoincost) return(false);
  357.  */
  358. if (!equali(a->joinid, b->joinid))
  359. return false;
  360. return true;
  361. }
  362. static bool
  363. _equalIndexPath(IndexPath *a, IndexPath *b)
  364. {
  365. if (!_equalPath((Path *) a, (Path *) b))
  366. return false;
  367. if (!equali(a->indexid, b->indexid))
  368. return false;
  369. if (!equal(a->indexqual, b->indexqual))
  370. return false;
  371. return true;
  372. }
  373. static bool
  374. _equalNestPath(NestPath *a, NestPath *b)
  375. {
  376. Assert(IsA_JoinPath(a));
  377. Assert(IsA_JoinPath(b));
  378. if (!_equalPath((Path *) a, (Path *) b))
  379. return false;
  380. if (!equal(a->pathinfo, b->pathinfo))
  381. return false;
  382. if (!equal(a->outerjoinpath, b->outerjoinpath))
  383. return false;
  384. if (!equal(a->innerjoinpath, b->innerjoinpath))
  385. return false;
  386. return true;
  387. }
  388. static bool
  389. _equalMergePath(MergePath *a, MergePath *b)
  390. {
  391. Assert(IsA(a, MergePath));
  392. Assert(IsA(b, MergePath));
  393. if (!_equalNestPath((NestPath *) a, (NestPath *) b))
  394. return false;
  395. if (!equal(a->path_mergeclauses, b->path_mergeclauses))
  396. return false;
  397. if (!equal(a->outersortkeys, b->outersortkeys))
  398. return false;
  399. if (!equal(a->innersortkeys, b->innersortkeys))
  400. return false;
  401. return true;
  402. }
  403. static bool
  404. _equalHashPath(HashPath *a, HashPath *b)
  405. {
  406. Assert(IsA(a, HashPath));
  407. Assert(IsA(b, HashPath));
  408. if (!_equalNestPath((NestPath *) a, (NestPath *) b))
  409. return false;
  410. if (!equal((a->path_hashclauses), (b->path_hashclauses)))
  411. return false;
  412. if (!equal(a->outerhashkeys, b->outerhashkeys))
  413. return false;
  414. if (!equal(a->innerhashkeys, b->innerhashkeys))
  415. return false;
  416. return true;
  417. }
  418. static bool
  419. _equalJoinKey(JoinKey *a, JoinKey *b)
  420. {
  421. Assert(IsA(a, JoinKey));
  422. Assert(IsA(b, JoinKey));
  423. if (!equal(a->outer, b->outer))
  424. return false;
  425. if (!equal(a->inner, b->inner))
  426. return false;
  427. return true;
  428. }
  429. static bool
  430. _equalMergeOrder(MergeOrder *a, MergeOrder *b)
  431. {
  432. if (a == (MergeOrder *) NULL && b == (MergeOrder *) NULL)
  433. return true;
  434. Assert(IsA(a, MergeOrder));
  435. Assert(IsA(b, MergeOrder));
  436. if (a->join_operator != b->join_operator)
  437. return false;
  438. if (a->left_operator != b->left_operator)
  439. return false;
  440. if (a->right_operator != b->right_operator)
  441. return false;
  442. if (a->left_type != b->left_type)
  443. return false;
  444. if (a->right_type != b->right_type)
  445. return false;
  446. return true;
  447. }
  448. static bool
  449. _equalHashInfo(HashInfo *a, HashInfo *b)
  450. {
  451. Assert(IsA(a, HashInfo));
  452. Assert(IsA(b, HashInfo));
  453. if (a->hashop != b->hashop)
  454. return false;
  455. return true;
  456. }
  457. /* XXX This equality function is a quick hack, should be
  458.  * fixed to compare all fields.
  459.  */
  460. static bool
  461. _equalIndexScan(IndexScan *a, IndexScan *b)
  462. {
  463. Assert(IsA(a, IndexScan));
  464. Assert(IsA(b, IndexScan));
  465. /*
  466.  * if(a->scan.plan.cost != b->scan.plan.cost) return(false);
  467.  */
  468. if (!equal(a->indxqual, b->indxqual))
  469. return false;
  470. if (a->scan.scanrelid != b->scan.scanrelid)
  471. return false;
  472. if (!equali(a->indxid, b->indxid))
  473. return false;
  474. return true;
  475. }
  476. static bool
  477. _equalSubPlan(SubPlan *a, SubPlan *b)
  478. {
  479. if (a->plan_id != b->plan_id)
  480. return false;
  481. if (!equal(a->sublink->oper, b->sublink->oper))
  482. return false;
  483. return true;
  484. }
  485. static bool
  486. _equalJoinInfo(JoinInfo *a, JoinInfo *b)
  487. {
  488. Assert(IsA(a, JoinInfo));
  489. Assert(IsA(b, JoinInfo));
  490. if (!equal(a->unjoined_relids, b->unjoined_relids))
  491. return false;
  492. if (!equal(a->jinfo_restrictinfo, b->jinfo_restrictinfo))
  493. return false;
  494. if (a->mergejoinable != b->mergejoinable)
  495. return false;
  496. if (a->hashjoinable != b->hashjoinable)
  497. return false;
  498. return true;
  499. }
  500. /*
  501.  * Stuff from execnodes.h
  502.  */
  503. /*
  504.  * EState is a subclass of Node.
  505.  */
  506. static bool
  507. _equalEState(EState *a, EState *b)
  508. {
  509. if (a->es_direction != b->es_direction)
  510. return false;
  511. if (!equal(a->es_range_table, b->es_range_table))
  512. return false;
  513. if (a->es_result_relation_info != b->es_result_relation_info)
  514. return false;
  515. return true;
  516. }
  517. /*
  518.  * Stuff from parsenodes.h
  519.  */
  520. static bool
  521. _equalQuery(Query *a, Query *b)
  522. {
  523. if (a->commandType != b->commandType)
  524. return false;
  525. if (!equal(a->utilityStmt, b->utilityStmt))
  526. return false;
  527. if (a->resultRelation != b->resultRelation)
  528. return false;
  529. if (a->into && b->into)
  530. {
  531. if (strcmp(a->into, b->into) != 0)
  532. return false;
  533. }
  534. else
  535. {
  536. if (a->into != b->into)
  537. return false;
  538. }
  539. if (a->isPortal != b->isPortal)
  540. return false;
  541. if (a->isBinary != b->isBinary)
  542. return false;
  543. if (a->isTemp != b->isTemp)
  544. return false;
  545. if (a->unionall != b->unionall)
  546. return false;
  547. if (a->hasAggs != b->hasAggs)
  548. return false;
  549. if (a->hasSubLinks != b->hasSubLinks)
  550. return false;
  551. if (a->uniqueFlag && b->uniqueFlag)
  552. {
  553. if (strcmp(a->uniqueFlag, b->uniqueFlag) != 0)
  554. return false;
  555. }
  556. else
  557. {
  558. if (a->uniqueFlag != b->uniqueFlag)
  559. return false;
  560. }
  561. if (!equal(a->sortClause, b->sortClause))
  562. return false;
  563. if (!equal(a->rtable, b->rtable))
  564. return false;
  565. if (!equal(a->targetList, b->targetList))
  566. return false;
  567. if (!equal(a->qual, b->qual))
  568. return false;
  569. if (!equal(a->rowMark, b->rowMark))
  570. return false;
  571. if (!equal(a->groupClause, b->groupClause))
  572. return false;
  573. if (!equal(a->havingQual, b->havingQual))
  574. return false;
  575. if (!equal(a->intersectClause, b->intersectClause))
  576. return false;
  577. if (!equal(a->unionClause, b->unionClause))
  578. return false;
  579. if (!equal(a->limitOffset, b->limitOffset))
  580. return false;
  581. if (!equal(a->limitCount, b->limitCount))
  582. return false;
  583. /*
  584.  * We do not check the internal-to-the-planner fields base_rel_list
  585.  * and join_rel_list.  They might not be set yet, and in any case they
  586.  * should be derivable from the other fields.
  587.  */
  588. return true;
  589. }
  590. static bool
  591. _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
  592. {
  593. if (a->relname && b->relname)
  594. {
  595. if (strcmp(a->relname, b->relname) != 0)
  596. return false;
  597. }
  598. else
  599. {
  600. if (a->relname != b->relname)
  601. return false;
  602. }
  603. if (a->refname && b->refname)
  604. {
  605. if (strcmp(a->refname, b->refname) != 0)
  606. return false;
  607. }
  608. else
  609. {
  610. if (a->refname != b->refname)
  611. return false;
  612. }
  613. if (a->relid != b->relid)
  614. return false;
  615. if (a->inh != b->inh)
  616. return false;
  617. if (a->inFromCl != b->inFromCl)
  618. return false;
  619. if (a->skipAcl != b->skipAcl)
  620. return false;
  621. return true;
  622. }
  623. static bool
  624. _equalTargetEntry(TargetEntry *a, TargetEntry *b)
  625. {
  626. if (!equal(a->resdom, b->resdom))
  627. return false;
  628. if (!equal(a->fjoin, b->fjoin))
  629. return false;
  630. if (!equal(a->expr, b->expr))
  631. return false;
  632. return true;
  633. }
  634. static bool
  635. _equalCaseExpr(CaseExpr *a, CaseExpr *b)
  636. {
  637. if (a->casetype != b->casetype)
  638. return false;
  639. if (!equal(a->arg, b->arg))
  640. return false;
  641. if (!equal(a->args, b->args))
  642. return false;
  643. if (!equal(a->defresult, b->defresult))
  644. return false;
  645. return true;
  646. }
  647. static bool
  648. _equalCaseWhen(CaseWhen *a, CaseWhen *b)
  649. {
  650. if (!equal(a->expr, b->expr))
  651. return false;
  652. if (!equal(a->result, b->result))
  653. return false;
  654. return true;
  655. }
  656. /*
  657.  * Stuff from pg_list.h
  658.  */
  659. static bool
  660. _equalValue(Value *a, Value *b)
  661. {
  662. if (a->type != b->type)
  663. return false;
  664. switch (a->type)
  665. {
  666. case T_String:
  667. return strcmp(a->val.str, b->val.str);
  668. case T_Integer:
  669. return a->val.ival == b->val.ival;
  670. case T_Float:
  671. return a->val.dval == b->val.dval;
  672. default:
  673. break;
  674. }
  675. return true;
  676. }
  677. /*
  678.  * equal
  679.  *   returns whether two nodes are equal
  680.  */
  681. bool
  682. equal(void *a, void *b)
  683. {
  684. bool retval = false;
  685. if (a == b)
  686. return true;
  687. /*
  688.  * note that a!=b, so only one of them can be NULL
  689.  */
  690. if (a == NULL || b == NULL)
  691. return false;
  692. /*
  693.  * are they the same type of nodes?
  694.  */
  695. if (nodeTag(a) != nodeTag(b))
  696. return false;
  697. switch (nodeTag(a))
  698. {
  699. case T_Resdom:
  700. retval = _equalResdom(a, b);
  701. break;
  702. case T_Fjoin:
  703. retval = _equalFjoin(a, b);
  704. break;
  705. case T_Expr:
  706. retval = _equalExpr(a, b);
  707. break;
  708. case T_Iter:
  709. retval = _equalIter(a, b);
  710. break;
  711. case T_Stream:
  712. retval = _equalStream(a, b);
  713. break;
  714. case T_Var:
  715. retval = _equalVar(a, b);
  716. break;
  717. case T_Array:
  718. retval = _equalArray(a, b);
  719. break;
  720. case T_ArrayRef:
  721. retval = _equalArrayRef(a, b);
  722. break;
  723. case T_Oper:
  724. retval = _equalOper(a, b);
  725. break;
  726. case T_Const:
  727. retval = _equalConst(a, b);
  728. break;
  729. case T_Param:
  730. retval = _equalParam(a, b);
  731. break;
  732. case T_Aggref:
  733. retval = _equalAggref(a, b);
  734. break;
  735. case T_Func:
  736. retval = _equalFunc(a, b);
  737. break;
  738. case T_RestrictInfo:
  739. retval = _equalRestrictInfo(a, b);
  740. break;
  741. case T_RelOptInfo:
  742. retval = _equalRelOptInfo(a, b);
  743. break;
  744. case T_JoinMethod:
  745. retval = _equalJoinMethod(a, b);
  746. break;
  747. case T_Path:
  748. retval = _equalPath(a, b);
  749. break;
  750. case T_IndexPath:
  751. retval = _equalIndexPath(a, b);
  752. break;
  753. case T_NestPath:
  754. retval = _equalNestPath(a, b);
  755. break;
  756. case T_MergePath:
  757. retval = _equalMergePath(a, b);
  758. break;
  759. case T_HashPath:
  760. retval = _equalHashPath(a, b);
  761. break;
  762. case T_JoinKey:
  763. retval = _equalJoinKey(a, b);
  764. break;
  765. case T_MergeOrder:
  766. retval = _equalMergeOrder(a, b);
  767. break;
  768. case T_HashInfo:
  769. retval = _equalHashInfo(a, b);
  770. break;
  771. case T_IndexScan:
  772. retval = _equalIndexScan(a, b);
  773. break;
  774. case T_SubPlan:
  775. retval = _equalSubPlan(a, b);
  776. break;
  777. case T_JoinInfo:
  778. retval = _equalJoinInfo(a, b);
  779. break;
  780. case T_EState:
  781. retval = _equalEState(a, b);
  782. break;
  783. case T_Integer:
  784. case T_String:
  785. case T_Float:
  786. retval = _equalValue(a, b);
  787. break;
  788. case T_List:
  789. {
  790. List    *la = (List *) a;
  791. List    *lb = (List *) b;
  792. List    *l;
  793. if (a == NULL && b == NULL)
  794. return true;
  795. if (length(a) != length(b))
  796. return false;
  797. foreach(l, la)
  798. {
  799. if (!equal(lfirst(l), lfirst(lb)))
  800. return false;
  801. lb = lnext(lb);
  802. }
  803. retval = true;
  804. }
  805. break;
  806. case T_Query:
  807. retval = _equalQuery(a, b);
  808. break;
  809. case T_RangeTblEntry:
  810. retval = _equalRangeTblEntry(a, b);
  811. break;
  812. case T_TargetEntry:
  813. retval = _equalTargetEntry(a, b);
  814. break;
  815. case T_CaseExpr:
  816. retval = _equalCaseExpr(a, b);
  817. break;
  818. case T_CaseWhen:
  819. retval = _equalCaseWhen(a, b);
  820. break;
  821. default:
  822. elog(NOTICE, "equal: don't know whether nodes of type %d are equal",
  823.  nodeTag(a));
  824. break;
  825. }
  826. return retval;
  827. }
  828. /*
  829.  * equali
  830.  *   compares two lists of integers
  831.  *
  832.  * XXX temp hack. needs something like T_IntList
  833.  */
  834. static bool
  835. equali(List *a, List *b)
  836. {
  837. List    *la = (List *) a;
  838. List    *lb = (List *) b;
  839. List    *l;
  840. if (a == NULL && b == NULL)
  841. return true;
  842. if (length(a) != length(b))
  843. return false;
  844. foreach(l, la)
  845. {
  846. if (lfirsti(l) != lfirsti(lb))
  847. return false;
  848. lb = lnext(lb);
  849. }
  850. return true;
  851. }