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