join bug fix: adapt keycmp to work with new order-checking feature
authorJim Meyering <meyering@redhat.com>
Sun, 23 Mar 2008 11:31:07 +0000 (12:31 +0100)
committerJim Meyering <meyering@redhat.com>
Tue, 25 Mar 2008 18:10:10 +0000 (19:10 +0100)
* src/join.c (keycmp): Add two join-field parameters.
(check_order, join): Update callers.
Reported by Dmitry V. Levin in
http://thread.gmane.org/gmane.comp.gnu.coreutils.bugs/12731/focus=13017
* tests/join/Test.pm (chkodr-7): New test for this fix.

src/join.c
tests/join/Test.pm

index 8f0d436..23ab78c 100644 (file)
@@ -300,7 +300,8 @@ freeline (struct line *line)
    Report an error and exit if the comparison fails.  */
 
 static int
-keycmp (struct line const *line1, struct line const *line2)
+keycmp (struct line const *line1, struct line const *line2,
+       size_t jf_1, size_t jf_2)
 {
   /* Start of field to compare in each file.  */
   char *beg1;
@@ -310,10 +311,10 @@ keycmp (struct line const *line1, struct line const *line2)
   size_t len2;         /* Length of fields to compare.  */
   int diff;
 
-  if (join_field_1 < line1->nfields)
+  if (jf_1 < line1->nfields)
     {
-      beg1 = line1->fields[join_field_1].beg;
-      len1 = line1->fields[join_field_1].len;
+      beg1 = line1->fields[jf_1].beg;
+      len1 = line1->fields[jf_1].len;
     }
   else
     {
@@ -321,10 +322,10 @@ keycmp (struct line const *line1, struct line const *line2)
       len1 = 0;
     }
 
-  if (join_field_2 < line2->nfields)
+  if (jf_2 < line2->nfields)
     {
-      beg2 = line2->fields[join_field_2].beg;
-      len2 = line2->fields[join_field_2].len;
+      beg2 = line2->fields[jf_2].beg;
+      len2 = line2->fields[jf_2].len;
     }
   else
     {
@@ -376,7 +377,8 @@ check_order (const struct line *prev,
     {
       if (!issued_disorder_warning[whatfile-1])
        {
-         if (keycmp (prev, current) > 0)
+         size_t join_field = whatfile == 1 ? join_field_1 : join_field_2;
+         if (keycmp (prev, current, join_field, join_field) > 0)
            {
              error ((check_input_order == CHECK_ORDER_ENABLED
                      ? EXIT_FAILURE : 0),
@@ -605,7 +607,8 @@ join (FILE *fp1, FILE *fp2)
   while (seq1.count && seq2.count)
     {
       size_t i;
-      diff = keycmp (&seq1.lines[0], &seq2.lines[0]);
+      diff = keycmp (&seq1.lines[0], &seq2.lines[0],
+                    join_field_1, join_field_2);
       if (diff < 0)
        {
          if (print_unpairables_1)
@@ -633,7 +636,8 @@ join (FILE *fp1, FILE *fp2)
            ++seq1.count;
            break;
          }
-      while (!keycmp (&seq1.lines[seq1.count - 1], &seq2.lines[0]));
+      while (!keycmp (&seq1.lines[seq1.count - 1], &seq2.lines[0],
+                     join_field_1, join_field_2));
 
       /* Keep reading lines from file2 as long as they continue to
          match the current line from file1.  */
@@ -645,7 +649,8 @@ join (FILE *fp1, FILE *fp2)
            ++seq2.count;
            break;
          }
-      while (!keycmp (&seq1.lines[0], &seq2.lines[seq2.count - 1]));
+      while (!keycmp (&seq1.lines[0], &seq2.lines[seq2.count - 1],
+                     join_field_1, join_field_2));
 
       if (print_pairables)
        {
index 6d91908..74fb326 100644 (file)
@@ -169,7 +169,11 @@ my @tv = (
 # --nocheck-order option had any effect.   We don't actually want to
 # guarantee that join produces this output on stdout.
 ['chkodr-6', '--nocheck-order',
- [" b 1\n a 2\n", " b Y\n c Z\n"], "b 1 Y\n", 0]
+ [" b 1\n a 2\n", " b Y\n c Z\n"], "b 1 Y\n", 0],
+
+# Before 6.10.143, this would mistakenly fail with the diagnostic:
+# join: File 1 is not in sorted order
+['chkodr-7', '-12', ["2 a\n1 b\n", ""], "", 0],
 )
 ;