~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/key.cc

  • Committer: Brian Aker
  • Date: 2010-04-20 18:36:10 UTC
  • mfrom: (1461.2.3 more-valgrind)
  • Revision ID: brian@gaz-20100420183610-qnhkalsqa892h8as
Merge Monty

Show diffs side-by-side

added added

removed removed

Lines of Context:
467
467
}
468
468
 
469
469
 
470
 
/*
471
 
  Compare two records in index order
472
 
  SYNOPSIS
473
 
    key_rec_cmp()
474
 
    key                         Index information
475
 
    rec0                        Pointer to table->record[0]
476
 
    first_rec                   Pointer to record compare with
477
 
    second_rec                  Pointer to record compare against first_rec
478
 
 
479
 
  DESCRIPTION
480
 
    This method is set-up such that it can be called directly from the
481
 
    priority queue and it is attempted to be optimised as much as possible
482
 
    since this will be called O(N * log N) times while performing a merge
483
 
    sort in various places in the code.
484
 
 
485
 
    We retrieve the pointer to table->record[0] using the fact that key_parts
486
 
    have an offset making it possible to calculate the start of the record.
487
 
    We need to get the diff to the compared record since none of the records
488
 
    being compared are stored in table->record[0].
489
 
 
490
 
    We first check for NULL values, if there are no NULL values we use
491
 
    a compare method that gets two field pointers and a max length
492
 
    and return the result of the comparison.
493
 
*/
494
 
 
495
 
int key_rec_cmp(void *key, unsigned char *first_rec, unsigned char *second_rec)
496
 
{
497
 
  KEY *key_info= (KEY*)key;
498
 
  uint32_t key_parts= key_info->key_parts, i= 0;
499
 
  KEY_PART_INFO *key_part= key_info->key_part;
500
 
  unsigned char *rec0= key_part->field->ptr - key_part->offset;
501
 
  ptrdiff_t first_diff= first_rec - rec0, sec_diff= second_rec - rec0;
502
 
  int result= 0;
503
 
 
504
 
  do
505
 
  {
506
 
    Field *field= key_part->field;
507
 
 
508
 
    if (key_part->null_bit)
509
 
    {
510
 
      /* The key_part can contain NULL values */
511
 
      bool first_is_null= field->is_null_in_record_with_offset(first_diff);
512
 
      bool sec_is_null= field->is_null_in_record_with_offset(sec_diff);
513
 
      /*
514
 
        NULL is smaller then everything so if first is NULL and the other
515
 
        not then we know that we should return -1 and for the opposite
516
 
        we should return +1. If both are NULL then we call it equality
517
 
        although it is a strange form of equality, we have equally little
518
 
        information of the real value.
519
 
      */
520
 
      if (!first_is_null)
521
 
      {
522
 
        if (!sec_is_null)
523
 
          ; /* Fall through, no NULL fields */
524
 
        else
525
 
        {
526
 
          return(1);
527
 
        }
528
 
      }
529
 
      else if (!sec_is_null)
530
 
      {
531
 
        return(-1);
532
 
      }
533
 
      else
534
 
        goto next_loop; /* Both were NULL */
535
 
    }
536
 
    /*
537
 
      No null values in the fields
538
 
      We use the virtual method cmp_max with a max length parameter.
539
 
      For most field types this translates into a cmp without
540
 
      max length. The exceptions are the BLOB and VARCHAR field types
541
 
      that take the max length into account.
542
 
    */
543
 
    result= field->cmp_max(field->ptr+first_diff, field->ptr+sec_diff,
544
 
                           key_part->length);
545
 
next_loop:
546
 
    key_part++;
547
 
  } while (!result && ++i < key_parts);
548
 
  return(result);
549
 
}
550
 
 
551
470
} /* namespace drizzled */