~ubuntu-branches/ubuntu/utopic/mariadb-5.5/utopic-security

« back to all changes in this revision

Viewing changes to sql/ha_partition.cc

  • Committer: Package Import Robot
  • Author(s): Otto Kekäläinen
  • Date: 2014-04-17 20:55:22 UTC
  • mfrom: (2.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20140417205522-wof4l36nxhlkn89m
* New upstream release, fixing the following security issues:
  * Corresponding MariaDB CVEs for Oracle SPU April 2014 (Closes: #745330)
    - CVE-2014-0384 
    - CVE-2014-2419 
    - CVE-2014-2430 
    - CVE-2014-2431 
    - CVE-2014-2432 
    - CVE-2014-2436 
    - CVE-2014-2438 
    - CVE-2014-2440
* Re-enabled TokuDB with "if arch amd64" in d/rules
* Applied patch to log init output better
  (Closes https://mariadb.atlassian.net/browse/MDEV-5957)

Show diffs side-by-side

added added

removed removed

Lines of Context:
80
80
static uint partition_flags();
81
81
static uint alter_table_flags(uint flags);
82
82
 
83
 
extern "C" int cmp_key_then_part_id(void *key_p, uchar *ref1, uchar *ref2);
 
83
extern "C" int cmp_key_part_id(void *key_p, uchar *ref1, uchar *ref2);
 
84
extern "C" int cmp_key_rowid_part_id(void *ptr, uchar *ref1, uchar *ref2);
84
85
 
85
86
static int partition_initialize(void *p)
86
87
{
4514
4515
    uint alloc_len;
4515
4516
    uint used_parts= bitmap_bits_set(&m_part_info->used_partitions);
4516
4517
    /* Allocate record buffer for each used partition. */
4517
 
    alloc_len= used_parts * (m_rec_length + PARTITION_BYTES_IN_POS);
 
4518
    m_priority_queue_rec_len= m_rec_length + PARTITION_BYTES_IN_POS;
 
4519
    if (!m_using_extended_keys)
 
4520
       m_priority_queue_rec_len += m_file[0]->ref_length;
 
4521
    alloc_len= used_parts * m_priority_queue_rec_len;
4518
4522
    /* Allocate a key for temporary use when setting up the scan. */
4519
4523
    alloc_len+= table_share->max_key_length;
4520
4524
 
4536
4540
      {
4537
4541
        DBUG_PRINT("info", ("init rec-buf for part %u", i));
4538
4542
        int2store(ptr, i);
4539
 
        ptr+= m_rec_length + PARTITION_BYTES_IN_POS;
 
4543
        ptr+= m_priority_queue_rec_len;
4540
4544
      }
4541
4545
    } while (++i < m_tot_parts);
4542
4546
    m_start_key.key= (const uchar*)ptr;
 
4547
    
4543
4548
    /* Initialize priority queue, initialized to reading forward. */
4544
 
    if (init_queue(&m_queue, used_parts, 0,
4545
 
                   0, cmp_key_then_part_id, (void*)m_curr_key_info, 0, 0))
 
4549
    int (*cmp_func)(void *, uchar *, uchar *);
 
4550
    void *cmp_arg;
 
4551
    if (!m_using_extended_keys)
 
4552
    {
 
4553
      cmp_func= cmp_key_rowid_part_id;
 
4554
      cmp_arg=  (void*)this;
 
4555
    }
 
4556
    else
 
4557
    {
 
4558
      cmp_func= cmp_key_part_id;
 
4559
      cmp_arg= (void*)m_curr_key_info;
 
4560
    }
 
4561
    if (init_queue(&m_queue, used_parts, 0, 0, cmp_func, cmp_arg, 0, 0))
4546
4562
    {
4547
4563
      my_free(m_ordered_rec_buffer);
4548
4564
      m_ordered_rec_buffer= NULL;
4609
4625
    DBUG_PRINT("info", ("Clustered pk, using pk as secondary cmp"));
4610
4626
    m_curr_key_info[1]= table->key_info+table->s->primary_key;
4611
4627
    m_curr_key_info[2]= NULL;
 
4628
    m_using_extended_keys= TRUE;
4612
4629
  }
4613
4630
  else
 
4631
  {
4614
4632
    m_curr_key_info[1]= NULL;
 
4633
    m_using_extended_keys= FALSE;
 
4634
  }
4615
4635
 
4616
4636
  if (init_record_priority_queue())
4617
4637
    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
4738
4758
}
4739
4759
 
4740
4760
 
4741
 
/*
4742
 
  @brief
4743
 
  Provide ordering by (key_value, partition_id). 
4744
 
  
4745
 
  @detail
4746
 
  Ordering by partition id is required so that key scans on key=const
4747
 
  return rows in rowid order (this is required for some variants of 
4748
 
  index_merge to work).  
4749
 
  
4750
 
  In ha_partition, rowid is a (partition_id, underlying_table_rowid). 
4751
 
  handle_ordered_index_scan must return rows ordered by (key, rowid).
4752
 
 
4753
 
  If two rows have the same key value and come from different partitions, 
4754
 
  it is sufficient to return them in the order of their partition_id.
4755
 
*/
4756
 
 
4757
 
extern "C" int cmp_key_then_part_id(void *key_p, uchar *ref1, uchar *ref2)
 
4761
/* Compare two part_no partition numbers */
 
4762
static int cmp_part_ids(uchar *ref1, uchar *ref2)
4758
4763
{
4759
 
  my_ptrdiff_t diff1, diff2;
4760
 
  int res;
4761
 
 
4762
 
  if ((res= key_rec_cmp(key_p, ref1 + PARTITION_BYTES_IN_POS, 
4763
 
                        ref2 + PARTITION_BYTES_IN_POS)))
4764
 
  {
4765
 
    return res;
4766
 
  }
4767
 
  
4768
4764
  /* The following was taken from ha_partition::cmp_ref */
4769
 
  diff1= ref2[1] - ref1[1];
4770
 
  diff2= ref2[0] - ref1[0];
 
4765
  my_ptrdiff_t diff1= ref2[1] - ref1[1];
 
4766
  my_ptrdiff_t diff2= ref2[0] - ref1[0];
4771
4767
  if (!diff1 && !diff2)
4772
4768
    return 0;
4773
4769
 
4784
4780
}
4785
4781
 
4786
4782
 
 
4783
/*
 
4784
  @brief
 
4785
    Provide ordering by (key_value, part_no). 
 
4786
*/
 
4787
 
 
4788
extern "C" int cmp_key_part_id(void *key_p, uchar *ref1, uchar *ref2)
 
4789
{
 
4790
  int res;
 
4791
  if ((res= key_rec_cmp(key_p, ref1 + PARTITION_BYTES_IN_POS, 
 
4792
                        ref2 + PARTITION_BYTES_IN_POS)))
 
4793
  {
 
4794
    return res;
 
4795
  }
 
4796
  return cmp_part_ids(ref1, ref2);
 
4797
}
 
4798
 
 
4799
/*
 
4800
  @brief
 
4801
    Provide ordering by (key_value, underying_table_rowid, part_no). 
 
4802
*/
 
4803
extern "C" int cmp_key_rowid_part_id(void *ptr, uchar *ref1, uchar *ref2)
 
4804
{
 
4805
  ha_partition *file= (ha_partition*)ptr;
 
4806
  int res;
 
4807
 
 
4808
  if ((res= key_rec_cmp(file->m_curr_key_info, ref1 + PARTITION_BYTES_IN_POS,
 
4809
                        ref2 + PARTITION_BYTES_IN_POS)))
 
4810
  {
 
4811
    return res;
 
4812
  }
 
4813
  if ((res= file->m_file[0]->cmp_ref(ref1 + PARTITION_BYTES_IN_POS + file->m_rec_length,
 
4814
                                     ref2 + PARTITION_BYTES_IN_POS + file->m_rec_length)))
 
4815
  {
 
4816
    return res;
 
4817
  }
 
4818
  return cmp_part_ids(ref1, ref2);
 
4819
}
 
4820
 
 
4821
 
4787
4822
/**
4788
4823
  Common routine for a number of index_read variants
4789
4824
 
5484
5519
  for (; first_used_part < m_part_spec.start_part; first_used_part++)
5485
5520
  {
5486
5521
    if (bitmap_is_set(&(m_part_info->used_partitions), first_used_part))
5487
 
      part_rec_buf_ptr+= m_rec_length + PARTITION_BYTES_IN_POS;
 
5522
      part_rec_buf_ptr+= m_priority_queue_rec_len;
5488
5523
  }
5489
5524
  DBUG_PRINT("info", ("m_part_spec.start_part %u first_used_part %u",
5490
5525
                      m_part_spec.start_part, first_used_part));
5539
5574
    if (!error)
5540
5575
    {
5541
5576
      found= TRUE;
 
5577
      if (!m_using_extended_keys)
 
5578
      {
 
5579
        file->position(rec_buf_ptr);
 
5580
        memcpy(rec_buf_ptr + m_rec_length, file->ref, file->ref_length);
 
5581
      }
5542
5582
      /*
5543
5583
        Initialize queue without order first, simply insert
5544
5584
      */
5555
5595
      m_key_not_found= true;
5556
5596
      saved_error= error;
5557
5597
    }
5558
 
    part_rec_buf_ptr+= m_rec_length + PARTITION_BYTES_IN_POS;
 
5598
    part_rec_buf_ptr+= m_priority_queue_rec_len;
5559
5599
  }
5560
5600
  if (found)
5561
5601
  {
5564
5604
      after that read the first entry and copy it to the buffer to return in.
5565
5605
    */
5566
5606
    queue_set_max_at_top(&m_queue, reverse_order);
5567
 
    queue_set_cmp_arg(&m_queue, (void*)m_curr_key_info);
 
5607
    queue_set_cmp_arg(&m_queue, m_using_extended_keys? m_curr_key_info : (void*)this);
5568
5608
    m_queue.elements= j - queue_first_element(&m_queue);
5569
5609
    queue_fix(&m_queue);
5570
5610
    return_top_record(buf);
5640
5680
      else if (error != HA_ERR_END_OF_FILE && error != HA_ERR_KEY_NOT_FOUND)
5641
5681
        DBUG_RETURN(error);
5642
5682
    }
5643
 
    part_buf+= m_rec_length + PARTITION_BYTES_IN_POS;
 
5683
    part_buf += m_priority_queue_rec_len;
5644
5684
  }
5645
5685
  DBUG_ASSERT(curr_rec_buf);
5646
5686
  bitmap_clear_all(&m_key_not_found_partitions);
5724
5764
  else
5725
5765
    error= file->ha_index_next_same(rec_buf, m_start_key.key,
5726
5766
                                    m_start_key.length);
 
5767
 
5727
5768
  if (error)
5728
5769
  {
5729
5770
    if (error == HA_ERR_END_OF_FILE)
5741
5782
    }
5742
5783
    DBUG_RETURN(error);
5743
5784
  }
 
5785
 
 
5786
  if (!m_using_extended_keys)
 
5787
  {
 
5788
    file->position(rec_buf);
 
5789
    memcpy(rec_buf + m_rec_length, file->ref, file->ref_length);
 
5790
  }
 
5791
 
5744
5792
  queue_replace_top(&m_queue);
5745
5793
  return_top_record(buf);
5746
5794
  DBUG_PRINT("info", ("Record returned from partition %u", m_top_entry));
7711
7759
 
7712
7760
int ha_partition::cmp_ref(const uchar *ref1, const uchar *ref2)
7713
7761
{
7714
 
  uint part_id;
 
7762
  int cmp;
7715
7763
  my_ptrdiff_t diff1, diff2;
7716
 
  handler *file;
7717
7764
  DBUG_ENTER("ha_partition::cmp_ref");
7718
7765
 
 
7766
  cmp = m_file[0]->cmp_ref((ref1 + PARTITION_BYTES_IN_POS),
 
7767
                           (ref2 + PARTITION_BYTES_IN_POS));
 
7768
  if (cmp)
 
7769
    DBUG_RETURN(cmp);
 
7770
 
7719
7771
  if ((ref1[0] == ref2[0]) && (ref1[1] == ref2[1]))
7720
7772
  {
7721
 
    part_id= uint2korr(ref1);
7722
 
    file= m_file[part_id];
7723
 
    DBUG_ASSERT(part_id < m_tot_parts);
7724
 
    DBUG_RETURN(file->cmp_ref((ref1 + PARTITION_BYTES_IN_POS),
7725
 
                              (ref2 + PARTITION_BYTES_IN_POS)));
 
7773
   /* This means that the references are same and are in same partition.*/
 
7774
    DBUG_RETURN(0);
7726
7775
  }
 
7776
 
 
7777
  /*
 
7778
    In Innodb we compare with either primary key value or global DB_ROW_ID so
 
7779
    it is not possible that the two references are equal and are in different
 
7780
    partitions, but in myisam it is possible since we are comparing offsets.
 
7781
    Remove this assert if DB_ROW_ID is changed to be per partition.
 
7782
  */
 
7783
  DBUG_ASSERT(!m_innodb);
 
7784
 
7727
7785
  diff1= ref2[1] - ref1[1];
7728
7786
  diff2= ref2[0] - ref1[0];
7729
7787
  if (diff1 > 0)