~ubuntu-branches/ubuntu/trusty/mariadb-5.5/trusty-proposed

« back to all changes in this revision

Viewing changes to sql/sql_partition.cc

  • Committer: Package Import Robot
  • Author(s): James Page, Otto Kekäläinen
  • Date: 2014-02-17 16:51:52 UTC
  • mfrom: (2.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20140217165152-k315d3175g865kkx
Tags: 5.5.35-1
[ Otto Kekäläinen ]
* New upstream release, fixing the following security issues:
  - Buffer overflow in client/mysql.cc (Closes: #737597).
    - CVE-2014-0001
  - http://www.oracle.com/technetwork/topics/security/cpujan2014-1972949.html
    - CVE-2013-5891
    - CVE-2013-5908
    - CVE-2014-0386
    - CVE-2014-0393
    - CVE-2014-0401
    - CVE-2014-0402
    - CVE-2014-0412
    - CVE-2014-0420
    - CVE-2014-0437
* Upstream https://mariadb.atlassian.net/browse/MDEV-4902
  fixes compatibility with Bison 3.0 (Closes: #733002)
* Updated Russian debconf translation (Closes: #734426)
* Updated Japanese debconf translation (Closes: #735284)
* Updated French debconf translation (Closes: #736480)
* Renamed SONAME properly (Closes: #732967)

Show diffs side-by-side

added added

removed removed

Lines of Context:
173
173
static int cmp_rec_and_tuple(part_column_list_val *val, uint32 nvals_in_rec);
174
174
static int cmp_rec_and_tuple_prune(part_column_list_val *val,
175
175
                                   uint32 n_vals_in_rec,
176
 
                                   bool tail_is_min);
 
176
                                   bool is_left_endpoint,
 
177
                                   bool include_endpoint);
177
178
 
178
179
/*
179
180
  Convert constants in VALUES definition to the character set the
3222
3223
}
3223
3224
 
3224
3225
 
3225
 
/*
3226
 
  Find the sub-array part_info->list_array that corresponds to given interval
3227
 
 
3228
 
  SYNOPSIS 
3229
 
    get_list_array_idx_for_endpoint()
3230
 
      part_info         Partitioning info (partitioning type must be LIST)
3231
 
      left_endpoint     TRUE  - the interval is [a; +inf) or (a; +inf)
3232
 
                        FALSE - the interval is (-inf; a] or (-inf; a)
3233
 
      include_endpoint  TRUE iff the interval includes the endpoint
3234
 
 
3235
 
  DESCRIPTION
3236
 
    This function finds the sub-array of part_info->list_array where values of
3237
 
    list_array[idx].list_value are contained within the specifed interval.
3238
 
    list_array is ordered by list_value, so
3239
 
    1. For [a; +inf) or (a; +inf)-type intervals (left_endpoint==TRUE), the 
3240
 
       sought sub-array starts at some index idx and continues till array end.
3241
 
       The function returns first number idx, such that 
3242
 
       list_array[idx].list_value is contained within the passed interval.
3243
 
       
3244
 
    2. For (-inf; a] or (-inf; a)-type intervals (left_endpoint==FALSE), the
3245
 
       sought sub-array starts at array start and continues till some last 
3246
 
       index idx.
3247
 
       The function returns first number idx, such that 
3248
 
       list_array[idx].list_value is NOT contained within the passed interval.
3249
 
       If all array elements are contained, part_info->num_list_values is
3250
 
       returned.
3251
 
 
3252
 
  NOTE
3253
 
    The caller will call this function and then will run along the sub-array of
3254
 
    list_array to collect partition ids. If the number of list values is 
3255
 
    significantly higher then number of partitions, this could be slow and
3256
 
    we could invent some other approach. The "run over list array" part is
3257
 
    already wrapped in a get_next()-like function.
3258
 
 
3259
 
  RETURN
3260
 
    The edge of corresponding sub-array of part_info->list_array
3261
 
*/
3262
 
 
3263
3226
uint32 get_partition_id_cols_list_for_endpoint(partition_info *part_info,
3264
3227
                                               bool left_endpoint,
3265
3228
                                               bool include_endpoint,
3267
3230
{
3268
3231
  part_column_list_val *list_col_array= part_info->list_col_array;
3269
3232
  uint num_columns= part_info->part_field_list.elements;
3270
 
  int list_index, cmp;
 
3233
  uint list_index;
3271
3234
  uint min_list_index= 0;
3272
 
  uint max_list_index= part_info->num_list_values - 1;
3273
 
  bool tailf= !(left_endpoint ^ include_endpoint);
 
3235
  uint max_list_index= part_info->num_list_values;
3274
3236
  DBUG_ENTER("get_partition_id_cols_list_for_endpoint");
3275
3237
 
 
3238
  /* Find the matching partition (including taking endpoint into account). */
3276
3239
  do
3277
3240
  {
 
3241
    /* Midpoint, adjusted down, so it can never be > last index. */
3278
3242
    list_index= (max_list_index + min_list_index) >> 1;
3279
 
    cmp= cmp_rec_and_tuple_prune(list_col_array + list_index*num_columns,
3280
 
                                 nparts, tailf);
3281
 
    if (cmp > 0)
 
3243
    if (cmp_rec_and_tuple_prune(list_col_array + list_index*num_columns,
 
3244
                                nparts, left_endpoint, include_endpoint) > 0)
3282
3245
      min_list_index= list_index + 1;
3283
 
    else if (cmp < 0)
3284
 
    {
3285
 
      if (!list_index)
3286
 
        goto notfound;
3287
 
      max_list_index= list_index - 1;
3288
 
    }
3289
 
    else 
3290
 
    {
3291
 
      DBUG_RETURN(list_index + test(!tailf));
3292
 
    }
3293
 
  } while (max_list_index >= min_list_index);
3294
 
  if (cmp > 0)
3295
 
    list_index++;
3296
 
notfound:
 
3246
    else
 
3247
      max_list_index= list_index;
 
3248
  } while (max_list_index > min_list_index);
 
3249
  list_index= max_list_index;
 
3250
 
 
3251
  /* Given value must be LESS THAN or EQUAL to the found partition. */
 
3252
  DBUG_ASSERT(list_index == part_info->num_list_values ||
 
3253
              (0 >= cmp_rec_and_tuple_prune(list_col_array +
 
3254
                                              list_index*num_columns,
 
3255
                                            nparts, left_endpoint,
 
3256
                                            include_endpoint)));
 
3257
  /* Given value must be GREATER THAN the previous partition. */
 
3258
  DBUG_ASSERT(list_index == 0 ||
 
3259
              (0 < cmp_rec_and_tuple_prune(list_col_array +
 
3260
                                            (list_index - 1)*num_columns,
 
3261
                                           nparts, left_endpoint,
 
3262
                                           include_endpoint)));
 
3263
 
 
3264
  if (!left_endpoint)
 
3265
  {
 
3266
    /* Set the end after this list tuple if not already after the last. */
 
3267
    if (list_index < part_info->num_parts)
 
3268
      list_index++;
 
3269
  }
 
3270
 
3297
3271
  DBUG_RETURN(list_index);
3298
3272
}
3299
3273
 
3300
3274
 
 
3275
/**
 
3276
  Find the sub-array part_info->list_array that corresponds to given interval.
 
3277
 
 
3278
  @param part_info         Partitioning info (partitioning type must be LIST)
 
3279
  @param left_endpoint     TRUE  - the interval is [a; +inf) or (a; +inf)
 
3280
                           FALSE - the interval is (-inf; a] or (-inf; a)
 
3281
  @param include_endpoint  TRUE iff the interval includes the endpoint
 
3282
 
 
3283
  This function finds the sub-array of part_info->list_array where values of
 
3284
  list_array[idx].list_value are contained within the specifed interval.
 
3285
  list_array is ordered by list_value, so
 
3286
  1. For [a; +inf) or (a; +inf)-type intervals (left_endpoint==TRUE), the
 
3287
     sought sub-array starts at some index idx and continues till array end.
 
3288
     The function returns first number idx, such that
 
3289
     list_array[idx].list_value is contained within the passed interval.
 
3290
 
 
3291
  2. For (-inf; a] or (-inf; a)-type intervals (left_endpoint==FALSE), the
 
3292
     sought sub-array starts at array start and continues till some last
 
3293
     index idx.
 
3294
     The function returns first number idx, such that
 
3295
     list_array[idx].list_value is NOT contained within the passed interval.
 
3296
     If all array elements are contained, part_info->num_list_values is
 
3297
     returned.
 
3298
 
 
3299
  @note The caller will call this function and then will run along the
 
3300
  sub-array of list_array to collect partition ids. If the number of list
 
3301
  values is significantly higher then number of partitions, this could be slow
 
3302
  and we could invent some other approach. The "run over list array" part is
 
3303
  already wrapped in a get_next()-like function.
 
3304
 
 
3305
  @return The index of corresponding sub-array of part_info->list_array.
 
3306
*/
 
3307
 
3301
3308
uint32 get_list_array_idx_for_endpoint_charset(partition_info *part_info,
3302
3309
                                               bool left_endpoint,
3303
3310
                                               bool include_endpoint)
5099
5106
    }
5100
5107
    else if (alter_info->flags & ALTER_REBUILD_PARTITION)
5101
5108
    {
 
5109
      set_engine_all_partitions(tab_part_info,
 
5110
                                tab_part_info->default_engine_type);
5102
5111
      if (set_part_state(alter_info, tab_part_info, PART_CHANGED))
5103
5112
      {
5104
5113
        my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), "REBUILD");
7345
7354
  return nparts;
7346
7355
}
7347
7356
 
7348
 
/*
7349
 
  RANGE(columns) partitioning: compare value bound and probe tuple.
7350
 
 
7351
 
  The value bound always is a full tuple (but may include the MAXVALUE
7352
 
  special value).
7353
 
 
7354
 
  The probe tuple may be a prefix of partitioning tuple. The tail_is_min
7355
 
  parameter specifies whether the suffix components should be assumed to
7356
 
  hold MAXVALUE
 
7357
/**
 
7358
  RANGE(columns) partitioning: compare partition value bound and probe tuple.
 
7359
 
 
7360
  @param val           Partition column values.
 
7361
  @param nvals_in_rec  Number of (prefix) fields to compare.
 
7362
 
 
7363
  @return Less than/Equal to/Greater than 0 if the record is L/E/G than val.
 
7364
 
 
7365
  @note The partition value bound is always a full tuple (but may include the
 
7366
  MAXVALUE special value). The probe tuple may be a prefix of partitioning
 
7367
  tuple.
7357
7368
*/
7358
7369
 
7359
7370
static int cmp_rec_and_tuple(part_column_list_val *val, uint32 nvals_in_rec)
7383
7394
}
7384
7395
 
7385
7396
 
 
7397
/**
 
7398
  Compare record and columns partition tuple including endpoint handling.
 
7399
 
 
7400
  @param  val               Columns partition tuple
 
7401
  @param  n_vals_in_rec     Number of columns to compare
 
7402
  @param  is_left_endpoint  True if left endpoint (part_tuple < rec or
 
7403
                            part_tuple <= rec)
 
7404
  @param  include_endpoint  If endpoint is included (part_tuple <= rec or
 
7405
                            rec <= part_tuple)
 
7406
 
 
7407
  @return Less than/Equal to/Greater than 0 if the record is L/E/G than
 
7408
  the partition tuple.
 
7409
 
 
7410
  @see get_list_array_idx_for_endpoint() and
 
7411
  get_partition_id_range_for_endpoint().
 
7412
*/
 
7413
 
7386
7414
static int cmp_rec_and_tuple_prune(part_column_list_val *val,
7387
7415
                                   uint32 n_vals_in_rec,
7388
 
                                   bool tail_is_min)
 
7416
                                   bool is_left_endpoint,
 
7417
                                   bool include_endpoint)
7389
7418
{
7390
7419
  int cmp;
7391
7420
  Field **field;
7392
 
  partition_info *part_info;
7393
7421
  if ((cmp= cmp_rec_and_tuple(val, n_vals_in_rec)))
7394
7422
    return cmp;
7395
 
  part_info= val->part_info;
7396
 
  field= part_info->part_field_array + n_vals_in_rec;
7397
 
  for (; *field; field++, val++)
 
7423
  field= val->part_info->part_field_array + n_vals_in_rec;
 
7424
  if (!(*field))
7398
7425
  {
7399
 
    if (tail_is_min)
7400
 
      return -1;
7401
 
    if (!tail_is_min && !val->max_value)
7402
 
      return +1;
 
7426
    /*
 
7427
      Full match, if right endpoint and not including the endpoint,
 
7428
      (rec < part) return lesser.
 
7429
    */
 
7430
    if (!is_left_endpoint && !include_endpoint)
 
7431
      return -4;
 
7432
 
 
7433
    /* Otherwise they are equal! */
 
7434
    return 0;
7403
7435
  }
7404
 
  return 0;
 
7436
  /*
 
7437
    The prefix is equal and there are more partition columns to compare.
 
7438
 
 
7439
    If including left endpoint or not including right endpoint
 
7440
    then the record is considered lesser compared to the partition.
 
7441
 
 
7442
    i.e:
 
7443
    part(10, x) <= rec(10, unknown) and rec(10, unknown) < part(10, x)
 
7444
    part <= rec -> lesser (i.e. this or previous partitions)
 
7445
    rec < part -> lesser (i.e. this or previous partitions)
 
7446
  */
 
7447
  if (is_left_endpoint == include_endpoint)
 
7448
    return -2;
 
7449
 
 
7450
  /*
 
7451
    If right endpoint and the first additional partition value
 
7452
    is MAXVALUE, then the record is lesser.
 
7453
  */
 
7454
  if (!is_left_endpoint && (val + n_vals_in_rec)->max_value)
 
7455
    return -3;
 
7456
 
 
7457
  /*
 
7458
    Otherwise the record is considered greater.
 
7459
 
 
7460
    rec <= part -> greater (i.e. does not match this partition, seek higher).
 
7461
    part < rec -> greater (i.e. does not match this partition, seek higher).
 
7462
  */
 
7463
  return 2;
7405
7464
}
7406
7465
 
7407
7466
 
7412
7471
                                        bool include_endpoint,
7413
7472
                                        uint32 num_parts);
7414
7473
 
7415
 
/*
7416
 
  Partitioning Interval Analysis: Initialize the iterator for "mapping" case
7417
 
 
7418
 
  SYNOPSIS
7419
 
    get_part_iter_for_interval_via_mapping()
7420
 
      part_info   Partition info
7421
 
      is_subpart  TRUE  - act for subpartitioning
7422
 
                  FALSE - act for partitioning
7423
 
      min_value   minimum field value, in opt_range key format.
7424
 
      max_value   minimum field value, in opt_range key format.
7425
 
      flags       Some combination of NEAR_MIN, NEAR_MAX, NO_MIN_RANGE,
7426
 
                  NO_MAX_RANGE.
7427
 
      part_iter   Iterator structure to be initialized
7428
 
 
7429
 
  DESCRIPTION
7430
 
    Initialize partition set iterator to walk over the interval in
7431
 
    ordered-array-of-partitions (for RANGE partitioning) or 
7432
 
    ordered-array-of-list-constants (for LIST partitioning) space.
7433
 
 
7434
 
  IMPLEMENTATION
7435
 
    This function is used when partitioning is done by
7436
 
    <RANGE|LIST>(ascending_func(t.field)), and we can map an interval in
7437
 
    t.field space into a sub-array of partition_info::range_int_array or
7438
 
    partition_info::list_array (see get_partition_id_range_for_endpoint,
7439
 
    get_list_array_idx_for_endpoint for details).
7440
 
    
7441
 
    The function performs this interval mapping, and sets the iterator to
7442
 
    traverse the sub-array and return appropriate partitions.
7443
 
    
7444
 
  RETURN
7445
 
    0 - No matching partitions (iterator not initialized)
7446
 
    1 - Ok, iterator intialized for traversal of matching partitions.
7447
 
   -1 - All partitions would match (iterator not initialized)
 
7474
/**
 
7475
  Get partition for RANGE COLUMNS endpoint.
 
7476
 
 
7477
  @param part_info         Partitioning metadata.
 
7478
  @param is_left_endpoint     True if left endpoint (const <=/< cols)
 
7479
  @param include_endpoint  True if range includes the endpoint (<=/>=)
 
7480
  @param nparts            Total number of partitions
 
7481
 
 
7482
  @return Partition id of matching partition.
 
7483
 
 
7484
  @see get_partition_id_cols_list_for_endpoint and
 
7485
  get_partition_id_range_for_endpoint.
7448
7486
*/
7449
7487
 
7450
7488
uint32 get_partition_id_cols_range_for_endpoint(partition_info *part_info,
7451
 
                                                bool left_endpoint,
 
7489
                                                bool is_left_endpoint,
7452
7490
                                                bool include_endpoint,
7453
7491
                                                uint32 nparts)
7454
7492
{
7455
 
  uint max_partition= part_info->num_parts - 1;
7456
 
  uint min_part_id= 0, max_part_id= max_partition, loc_part_id;
 
7493
  uint min_part_id= 0, max_part_id= part_info->num_parts, loc_part_id;
7457
7494
  part_column_list_val *range_col_array= part_info->range_col_array;
7458
7495
  uint num_columns= part_info->part_field_list.elements;
7459
 
  bool tailf= !(left_endpoint ^ include_endpoint);
7460
7496
  DBUG_ENTER("get_partition_id_cols_range_for_endpoint");
7461
7497
 
7462
 
  /* Get the partitioning function value for the endpoint */
7463
 
  while (max_part_id > min_part_id)
7464
 
  {
7465
 
    loc_part_id= (max_part_id + min_part_id + 1) >> 1;
7466
 
    if (cmp_rec_and_tuple_prune(range_col_array + loc_part_id*num_columns,
7467
 
                                nparts, tailf) >= 0)
7468
 
      min_part_id= loc_part_id + 1;
7469
 
    else
7470
 
      max_part_id= loc_part_id - 1;
7471
 
  }
7472
 
  loc_part_id= max_part_id;
7473
 
  if (loc_part_id < max_partition && 
7474
 
      cmp_rec_and_tuple_prune(range_col_array + (loc_part_id+1)*num_columns,
7475
 
                              nparts, tailf) >= 0
7476
 
      )
7477
 
  {
7478
 
     loc_part_id++;
7479
 
  }
7480
 
  if (left_endpoint)
7481
 
  {
7482
 
    if (cmp_rec_and_tuple_prune(range_col_array + loc_part_id*num_columns,
7483
 
                                nparts, tailf) >= 0)
7484
 
      loc_part_id++;
7485
 
  }
7486
 
  else 
7487
 
  {
7488
 
    if (loc_part_id < max_partition)
7489
 
    {
7490
 
      int res= cmp_rec_and_tuple_prune(range_col_array +
 
7498
  /* Find the matching partition (including taking endpoint into account). */
 
7499
  do
 
7500
  {
 
7501
    /* Midpoint, adjusted down, so it can never be > last partition. */
 
7502
    loc_part_id= (max_part_id + min_part_id) >> 1;
 
7503
    if (0 <= cmp_rec_and_tuple_prune(range_col_array +
7491
7504
                                       loc_part_id * num_columns,
7492
 
                                       nparts, tailf);
7493
 
      if (!res)
7494
 
        loc_part_id += test(include_endpoint);
7495
 
      else if (res > 0)
7496
 
        loc_part_id++;
7497
 
    }
7498
 
    loc_part_id++;
 
7505
                                     nparts,
 
7506
                                     is_left_endpoint,
 
7507
                                     include_endpoint))
 
7508
      min_part_id= loc_part_id + 1;
 
7509
    else
 
7510
      max_part_id= loc_part_id;
 
7511
  } while (max_part_id > min_part_id);
 
7512
  loc_part_id= max_part_id;
 
7513
 
 
7514
  /* Given value must be LESS THAN the found partition. */
 
7515
  DBUG_ASSERT(loc_part_id == part_info->num_parts ||
 
7516
              (0 > cmp_rec_and_tuple_prune(range_col_array +
 
7517
                                             loc_part_id * num_columns,
 
7518
                                           nparts, is_left_endpoint,
 
7519
                                           include_endpoint)));
 
7520
  /* Given value must be GREATER THAN or EQUAL to the previous partition. */
 
7521
  DBUG_ASSERT(loc_part_id == 0 ||
 
7522
              (0 <= cmp_rec_and_tuple_prune(range_col_array +
 
7523
                                              (loc_part_id - 1) * num_columns,
 
7524
                                            nparts, is_left_endpoint,
 
7525
                                            include_endpoint)));
 
7526
 
 
7527
  if (!is_left_endpoint)
 
7528
  {
 
7529
    /* Set the end after this partition if not already after the last. */
 
7530
    if (loc_part_id < part_info->num_parts)
 
7531
      loc_part_id++;
7499
7532
  }
7500
7533
  DBUG_RETURN(loc_part_id);
7501
7534
}
7568
7601
}
7569
7602
 
7570
7603
 
 
7604
/**
 
7605
  Partitioning Interval Analysis: Initialize the iterator for "mapping" case
 
7606
 
 
7607
  @param part_info   Partition info
 
7608
  @param is_subpart  TRUE  - act for subpartitioning
 
7609
                     FALSE - act for partitioning
 
7610
  @param store_length_array  Ignored.
 
7611
  @param min_value   minimum field value, in opt_range key format.
 
7612
  @param max_value   minimum field value, in opt_range key format.
 
7613
  @param min_len     Ignored.
 
7614
  @param max_len     Ignored.
 
7615
  @param flags       Some combination of NEAR_MIN, NEAR_MAX, NO_MIN_RANGE,
 
7616
                     NO_MAX_RANGE.
 
7617
  @param part_iter   Iterator structure to be initialized
 
7618
 
 
7619
  @details Initialize partition set iterator to walk over the interval in
 
7620
  ordered-array-of-partitions (for RANGE partitioning) or
 
7621
  ordered-array-of-list-constants (for LIST partitioning) space.
 
7622
 
 
7623
  This function is used when partitioning is done by
 
7624
  <RANGE|LIST>(ascending_func(t.field)), and we can map an interval in
 
7625
  t.field space into a sub-array of partition_info::range_int_array or
 
7626
  partition_info::list_array (see get_partition_id_range_for_endpoint,
 
7627
  get_list_array_idx_for_endpoint for details).
 
7628
 
 
7629
  The function performs this interval mapping, and sets the iterator to
 
7630
  traverse the sub-array and return appropriate partitions.
 
7631
 
 
7632
  @return Status of iterator
 
7633
    @retval 0   No matching partitions (iterator not initialized)
 
7634
    @retval 1   Ok, iterator intialized for traversal of matching partitions.
 
7635
    @retval -1  All partitions would match (iterator not initialized)
 
7636
*/
 
7637
 
7571
7638
int get_part_iter_for_interval_via_mapping(partition_info *part_info,
7572
7639
                                           bool is_subpart,
7573
7640
                                           uint32 *store_length_array, /* ignored */