]> granicus.if.org Git - postgresql/commitdiff
Replace insertion sort in contrib/intarray with qsort().
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 16 Mar 2015 03:22:03 +0000 (23:22 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 16 Mar 2015 03:22:03 +0000 (23:22 -0400)
It's all very well to claim that a simplistic sort is fast in easy
cases, but O(N^2) in the worst case is not good ... especially if the
worst case is as easy to hit as "descending order input".  Replace that
bit with our standard qsort.

Per bug #12866 from Maksym Boguk.  Back-patch to all active branches.

contrib/intarray/_int_tool.c

index 780b28bc3f977bafdd9cd16098b58a2742d2cd94..c377f6ee17a3a37abbf7fe627eec23b64f1ac320 100644 (file)
@@ -195,39 +195,38 @@ rt__int_size(ArrayType *a, float *size)
        return;
 }
 
+/* qsort_arg comparison function for isort() */
+static int
+isort_cmp(const void *a, const void *b, void *arg)
+{
+       int4            aval = *((const int4 *) a);
+       int4            bval = *((const int4 *) b);
+
+       if (aval < bval)
+               return -1;
+       if (aval > bval)
+               return 1;
+
+       /*
+        * Report if we have any duplicates.  If there are equal keys, qsort must
+        * compare them at some point, else it wouldn't know whether one should go
+        * before or after the other.
+        */
+       *((bool *) arg) = true;
+       return 0;
+}
 
-/* len >= 2 */
+/* Sort the given data (len >= 2).  Return true if any duplicates found */
 bool
 isort(int4 *a, int len)
 {
-       int4            tmp,
-                               index;
-       int4       *cur,
-                          *end;
-       bool            r = FALSE;
-
-       end = a + len;
-       do
-       {
-               index = 0;
-               cur = a + 1;
-               while (cur < end)
-               {
-                       if (*(cur - 1) > *cur)
-                       {
-                               tmp = *(cur - 1);
-                               *(cur - 1) = *cur;
-                               *cur = tmp;
-                               index = 1;
-                       }
-                       else if (!r && *(cur - 1) == *cur)
-                               r = TRUE;
-                       cur++;
-               }
-       } while (index);
+       bool            r = false;
+
+       qsort_arg(a, len, sizeof(int4), isort_cmp, (void *) &r);
        return r;
 }
 
+/* Create a new int array with room for "num" elements */
 ArrayType *
 new_intArrayType(int num)
 {