Currently, equal() does the following for List nodes:
case T_List:
{
List *la = (List *) a;
List *lb = (List *) b;
List *l;
/*
* Try to reject by length check before we grovel through
* all the elements...
*/
if (length(la) != length(lb))
return false;
foreach(l, la)
{
if (!equal(lfirst(l), lfirst(lb)))
return false;
lb = lnext(lb);
}
retval = true;
}
break;
This code is inefficient, however: length() requires iterating through
the entire list, so this code scans both lists twice. The attached patch
improves this by implementing equal() with a single scan of both lists.
-Neil
Index: src/backend/nodes/equalfuncs.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/nodes/equalfuncs.c,v
retrieving revision 1.209
diff -c -r1.209 equalfuncs.c
*** src/backend/nodes/equalfuncs.c 17 Aug 2003 23:43:26 -0000 1.209
--- src/backend/nodes/equalfuncs.c 3 Nov 2003 09:10:21 -0000
***************
*** 1779,1799 ****
{
List *la = (List *) a;
List *lb = (List *) b;
- List *l;
! /*
! * Try to reject by length check before we grovel through
! * all the elements...
! */
! if (length(la) != length(lb))
! return false;
! foreach(l, la)
{
! if (!equal(lfirst(l), lfirst(lb)))
return false;
lb = lnext(lb);
}
! retval = true;
}
break;
--- 1779,1801 ----
{
List *la = (List *) a;
List *lb = (List *) b;
! while (la != NIL && lb != NIL)
{
! if (!equal(lfirst(la), lfirst(lb)))
return false;
+ la = lnext(la);
lb = lnext(lb);
}
!
! /*
! * If we ran out of elements in one list before the
! * other, then the two lists cannot be equal
! */
! if (la != NIL || lb != NIL)
! retval = false;
! else
! retval = true;
}
break;
---------------------------(end of broadcast)---------------------------
TIP 8: explain analyze is your friend