Hi,
[I'm trying to share some of my thoughts about intarray contrib module.
If this is the wrong way to achieve this, please warn me. (Should I
first get in touch with Teodor Sigaev and Oleg Bartunov?)]
[6]
_int_same() in _int_op.c looks like making some redundant sorting and
not taking advantage of sorted arrays while comparing each other. Here's
the related code piece:
SORT(a);
SORT(b);
na = ARRNELEMS(a);
nb = ARRNELEMS(b);
da = ARRPTR(a);
db = ARRPTR(b);
result = FALSE;
if (na == nb)
{
result = TRUE;
for (n = 0; n < na; n++)
if (da[n] != db[n])
{
result = FALSE;
break;
}
}
IMHO, SORT() macro should be called after "if (na == nb)" block. (SORT()
doesn't remove duplicates.) Also, in the inner block, while comparing
two arrays, we can take advantage of sorting of arrays. While current
behaviour is like
if (A[0] == B[0] && A[1] == B[1] && ...)
we can replace it with sth like
if (A[0] == B[0] && A[ N] == B[ N] &&
A[1] == B[1] && A[N-1] == B[N-1] &&
...)
Attached patch tries to implement both behaviours mentioned above and
some minor hacking for arrays of 1,2 and 3 items.
Regards.
Index: contrib/intarray/_int_op.c
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/intarray/_int_op.c,v
retrieving revision 1.4
diff -c -r1.4 _int_op.c
*** contrib/intarray/_int_op.c 19 Nov 2005 03:00:09 -0000 1.4
--- contrib/intarray/_int_op.c 8 May 2006 18:50:43 -0000
***************
*** 69,77 ****
ArrayType *b = (ArrayType *)
DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
int na,
nb;
- int n;
- int *da,
- *db;
bool result;
bool avoid;
bool bvoid;
--- 69,74 ----
***************
*** 83,106 ****
if (avoid || bvoid)
return (avoid && bvoid) ? TRUE : FALSE;
- SORT(a);
- SORT(b);
na = ARRNELEMS(a);
nb = ARRNELEMS(b);
! da = ARRPTR(a);
! db = ARRPTR(b);
!
result = FALSE;
if (na == nb)
{
! result = TRUE;
! for (n = 0; n < na; n++)
! if (da[n] != db[n])
! {
! result = FALSE;
break;
}
}
pfree(a);
--- 80,155 ----
if (avoid || bvoid)
return (avoid && bvoid) ? TRUE : FALSE;
na = ARRNELEMS(a);
nb = ARRNELEMS(b);
!
result = FALSE;
if (na == nb)
{
! int *da;
! int *db;
!
! SORT(a);
! SORT(b);
! da = ARRPTR(a);
! db = ARRPTR(b);
!
! switch (na)
! {
! /*
! * Some little hack for small length arrays.
! */
! case 1:
! result = (da[0] == db[0]) ? TRUE : FALSE;
break;
+
+ case 2:
+ result = (da[0] == db[0] &&
+ da[1] == db[1]) ? TRUE :
FALSE;
+ break;
+
+ case 3:
+ result = (da[0] == db[0] &&
+ da[1] == db[1] &&
+ da[2] == db[2]) ? TRUE :
FALSE;
+ break;
+
+ /*
+ * Instead of making a brute force comparison, trying
to take
+ * advantage of sorted arrays.
+ */
+ default:
+ {
+ int head = 0;
+ int toe = na - 1;
+
+ result = TRUE;
+
+ /*
+ * Don't bother with even length arrays.
Consume their first
+ * element and carry on as arrays' lengths are
odd.
+ */
+ if (na % 2 == 0)
+ {
+ result = (*da++ == *db++) ? TRUE :
FALSE;
+ toe--;
+ }
+
+ if (result == TRUE)
+ while (head <= toe)
+ {
+ if (da[head] != db[head] ||
da[toe] != db[toe])
+ {
+ result = FALSE;
+ break;
+ }
+
+ head++;
+ toe--;
+ }
}
+ }
}
pfree(a);
---------------------------(end of broadcast)---------------------------
TIP 9: In versions below 8.0, the planner will ignore your desire to
choose an index scan if your joining column's datatypes do not
match