~jlukas79/+junk/mysql-server

« back to all changes in this revision

Viewing changes to sql/ha_partition.cc

manual merge 6.0-main --> 6.0-bka-review

Show diffs side-by-side

added added

removed removed

Lines of Context:
160
160
 
161
161
ha_partition::ha_partition(handlerton *hton, TABLE_SHARE *share)
162
162
  :handler(hton, share), m_part_info(NULL), m_create_handler(FALSE),
163
 
   m_is_sub_partitioned(0), is_clone(FALSE)
 
163
   m_is_sub_partitioned(0), is_clone(FALSE), auto_increment_lock(FALSE),
 
164
   auto_increment_safe_stmt_log_lock(FALSE)
164
165
{
165
166
  DBUG_ENTER("ha_partition::ha_partition(table)");
166
167
  init_handler_variables();
182
183
ha_partition::ha_partition(handlerton *hton, partition_info *part_info)
183
184
  :handler(hton, NULL), m_part_info(part_info),
184
185
   m_create_handler(TRUE),
185
 
   m_is_sub_partitioned(m_part_info->is_sub_partitioned()), is_clone(FALSE)
 
186
   m_is_sub_partitioned(m_part_info->is_sub_partitioned()), is_clone(FALSE),
 
187
   auto_increment_lock(FALSE), auto_increment_safe_stmt_log_lock(FALSE)
186
188
{
187
189
  DBUG_ENTER("ha_partition::ha_partition(part_info)");
188
190
  init_handler_variables();
641
643
        part_elem->part_state= PART_IS_DROPPED;
642
644
    }
643
645
  } while (++i < no_parts);
644
 
  VOID(sync_ddl_log());
 
646
  (void) sync_ddl_log();
645
647
  DBUG_RETURN(error);
646
648
}
647
649
 
735
737
        delete file;
736
738
      }
737
739
    } while (++i < temp_partitions);
738
 
    VOID(sync_ddl_log());
 
740
    (void) sync_ddl_log();
739
741
  }
740
742
  i= 0;
741
743
  do
788
790
              error= ret_error;
789
791
            else if (deactivate_ddl_log_entry(sub_elem->log_entry->entry_pos))
790
792
              error= 1;
791
 
            VOID(sync_ddl_log());
 
793
            (void) sync_ddl_log();
792
794
            delete file;
793
795
          }
794
796
          file= get_new_handler(0, thd->mem_root,
823
825
            error= ret_error;
824
826
          else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos))
825
827
            error= 1;
826
 
          VOID(sync_ddl_log());
 
828
          (void) sync_ddl_log();
827
829
          delete file;
828
830
        }
829
831
        file= get_new_handler(0, thd->mem_root,
844
846
      }
845
847
    }
846
848
  } while (++i < no_parts);
847
 
  VOID(sync_ddl_log());
 
849
  (void) sync_ddl_log();
848
850
  DBUG_RETURN(error);
849
851
}
850
852
 
1180
1182
    assumes that external_lock() is last call that may fail here.
1181
1183
    Otherwise see description for cleanup_new_partition().
1182
1184
  */
1183
 
  if ((error= file->ha_external_lock(current_thd, m_lock_type)))
 
1185
  if ((error= file->ha_external_lock(ha_thd(), m_lock_type)))
1184
1186
    goto error;
1185
1187
 
1186
1188
  DBUG_RETURN(0);
1187
1189
error:
1188
1190
  if (create_flag)
1189
 
    VOID(file->ha_delete_table(part_name));
 
1191
    (void) file->ha_delete_table(part_name);
1190
1192
  DBUG_RETURN(error);
1191
1193
}
1192
1194
 
1268
1270
 
1269
1271
int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
1270
1272
                                    const char *path,
1271
 
                                    ulonglong *copied,
1272
 
                                    ulonglong *deleted,
 
1273
                                    ulonglong * const copied,
 
1274
                                    ulonglong * const deleted,
1273
1275
                                    const uchar *pack_frm_data
1274
1276
                                    __attribute__((unused)),
1275
1277
                                    size_t pack_frm_len
1286
1288
  int error= 1;
1287
1289
  bool first;
1288
1290
  uint temp_partitions= m_part_info->temp_partitions.elements;
1289
 
  THD *thd= current_thd;
 
1291
  THD *thd= ha_thd();
1290
1292
  DBUG_ENTER("ha_partition::change_partitions");
1291
1293
 
1292
1294
  m_reorged_parts= 0;
1554
1556
    partitions.
1555
1557
*/
1556
1558
 
1557
 
int ha_partition::copy_partitions(ulonglong *copied, ulonglong *deleted)
 
1559
int ha_partition::copy_partitions(ulonglong * const copied,
 
1560
                                  ulonglong * const deleted)
1558
1561
{
1559
1562
  uint reorg_part= 0;
1560
1563
  int result= 0;
1600
1603
           table since it doesn't fit into any partition any longer due to
1601
1604
           changed partitioning ranges or list values.
1602
1605
        */
1603
 
        deleted++;
 
1606
        (*deleted)++;
1604
1607
      }
1605
1608
      else
1606
1609
      {
1607
1610
        THD *thd= ha_thd();
1608
1611
        /* Copy record to new handler */
1609
 
        copied++;
 
1612
        (*copied)++;
1610
1613
        tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */
1611
1614
        result= m_new_file[new_part]->ha_write_row(m_rec0);
1612
1615
        reenable_binlog(thd);
1646
1649
    create_info->auto_increment_value= stats.auto_increment_value;
1647
1650
 
1648
1651
  create_info->data_file_name= create_info->index_file_name = NULL;
 
1652
  create_info->tablespace= table_share->tablespace;
1649
1653
  return;
1650
1654
}
1651
1655
 
1727
1731
  handler **file, **abort_file;
1728
1732
  DBUG_ENTER("del_ren_cre_table()");
1729
1733
 
1730
 
  if (get_from_handler_file(from, current_thd->mem_root))
 
1734
  if (get_from_handler_file(from, ha_thd()->mem_root))
1731
1735
    DBUG_RETURN(TRUE);
1732
1736
  DBUG_ASSERT(m_file_buffer);
1733
1737
  name_buffer_ptr= m_name_buffer_ptr;
1764
1768
  {
1765
1769
    create_partition_name(from_buff, from, name_buffer_ptr, NORMAL_PART_NAME,
1766
1770
                          FALSE);
1767
 
    VOID((*file)->ha_delete_table((const char*) from_buff));
 
1771
    (void) (*file)->ha_delete_table((const char*) from_buff);
1768
1772
    name_buffer_ptr= strend(name_buffer_ptr) + 1;
1769
1773
  }
1770
1774
  DBUG_RETURN(error);
1807
1811
      return part_elem;
1808
1812
  }
1809
1813
  DBUG_ASSERT(0);
1810
 
  my_error(ER_OUT_OF_RESOURCES, MYF(0));
1811
 
  current_thd->fatal_error();                   // Abort
 
1814
  my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
1812
1815
  return NULL;
1813
1816
}
1814
1817
 
1842
1845
{
1843
1846
  int error= 0;
1844
1847
  const char *partition_name;
1845
 
  THD *thd= current_thd;
 
1848
  THD *thd= ha_thd();
1846
1849
  DBUG_ENTER("set_up_table_before_create");
1847
1850
 
1848
1851
  if (!part_elem)
1867
1870
  }
1868
1871
  info->index_file_name= part_elem->index_file_name;
1869
1872
  info->data_file_name= part_elem->data_file_name;
 
1873
  info->tablespace= part_elem->tablespace_name;
1870
1874
  DBUG_RETURN(0);
1871
1875
}
1872
1876
 
2038
2042
  {
2039
2043
    result= my_write(file, (uchar *) file_buffer, tot_len_byte,
2040
2044
                     MYF(MY_WME | MY_NABP)) != 0;
2041
 
    VOID(my_close(file, MYF(0)));
 
2045
    (void) my_close(file, MYF(0));
2042
2046
  }
2043
2047
  else
2044
2048
    result= TRUE;
2224
2228
  len_bytes= 4 * len_words;
2225
2229
  if (!(file_buffer= (char*) my_malloc(len_bytes, MYF(0))))
2226
2230
    goto err1;
2227
 
  VOID(my_seek(file, 0, MY_SEEK_SET, MYF(0)));
 
2231
  my_seek(file, 0, MY_SEEK_SET, MYF(0));
2228
2232
  if (my_read(file, (uchar *) file_buffer, len_bytes, MYF(MY_NABP)))
2229
2233
    goto err2;
2230
2234
 
2238
2242
  tot_partition_words= (m_tot_parts + 3) / 4;
2239
2243
  engine_array= (handlerton **) my_alloca(m_tot_parts * sizeof(handlerton*));
2240
2244
  for (i= 0; i < m_tot_parts; i++)
2241
 
    engine_array[i]= ha_resolve_by_legacy_type(current_thd,
 
2245
    engine_array[i]= ha_resolve_by_legacy_type(ha_thd(),
2242
2246
                                               (enum legacy_db_type)
2243
2247
                                               *(uchar *) ((file_buffer) + 12 + i));
2244
2248
  address_tot_name_len= file_buffer + 12 + 4 * tot_partition_words;
2246
2250
  if (len_words != (tot_partition_words + tot_name_words + 4))
2247
2251
    goto err3;
2248
2252
  name_buffer_ptr= file_buffer + 16 + 4 * tot_partition_words;
2249
 
  VOID(my_close(file, MYF(0)));
 
2253
  (void) my_close(file, MYF(0));
2250
2254
  m_file_buffer= file_buffer;          // Will be freed in clear_handler_file()
2251
2255
  m_name_buffer_ptr= name_buffer_ptr;
2252
2256
  
2271
2275
err2:
2272
2276
  my_free(file_buffer, MYF(0));
2273
2277
err1:
2274
 
  VOID(my_close(file, MYF(0)));
 
2278
  (void) my_close(file, MYF(0));
2275
2279
  DBUG_RETURN(TRUE);
2276
2280
}
2277
2281
 
2309
2313
  uint alloc_len;
2310
2314
  handler **file;
2311
2315
  char name_buff[FN_REFLEN];
 
2316
  bool is_not_tmp_table= (table_share->tmp_table == NO_TMP_TABLE);
2312
2317
  DBUG_ENTER("ha_partition::open");
2313
2318
 
 
2319
  DBUG_ASSERT(table->s == table_share);
2314
2320
  ref_length= 0;
2315
2321
  m_mode= mode;
2316
2322
  m_open_test_lock= test_if_locked;
2319
2325
    DBUG_RETURN(1);
2320
2326
  m_start_key.length= 0;
2321
2327
  m_rec0= table->record[0];
2322
 
  m_rec_length= table->s->reclength;
 
2328
  m_rec_length= table_share->reclength;
2323
2329
  alloc_len= m_tot_parts * (m_rec_length + PARTITION_BYTES_IN_POS);
2324
 
  alloc_len+= table->s->max_key_length;
 
2330
  alloc_len+= table_share->max_key_length;
2325
2331
  if (!m_ordered_rec_buffer)
2326
2332
  {
2327
2333
    if (!(m_ordered_rec_buffer= (uchar*)my_malloc(alloc_len, MYF(MY_WME))))
2394
2400
    goto err_handler;
2395
2401
 
2396
2402
  /*
 
2403
    Use table_share->ha_data to share auto_increment_value among all handlers
 
2404
    for the same table.
 
2405
  */
 
2406
  if (is_not_tmp_table)
 
2407
    pthread_mutex_lock(&table_share->LOCK_ha_data);
 
2408
  if (!table_share->ha_data)
 
2409
  {
 
2410
    HA_DATA_PARTITION *ha_data;
 
2411
    /* currently only needed for auto_increment */
 
2412
    table_share->ha_data= ha_data= (HA_DATA_PARTITION*)
 
2413
                                   alloc_root(&table_share->mem_root,
 
2414
                                              sizeof(HA_DATA_PARTITION));
 
2415
    if (!ha_data)
 
2416
      goto err_handler;
 
2417
    DBUG_PRINT("info", ("table_share->ha_data 0x%p", ha_data));
 
2418
    bzero(ha_data, sizeof(HA_DATA_PARTITION));
 
2419
  }
 
2420
  if (is_not_tmp_table)
 
2421
    pthread_mutex_unlock(&table_share->LOCK_ha_data);
 
2422
  /*
2397
2423
    Some handlers update statistics as part of the open call. This will in
2398
2424
    some cases corrupt the statistics of the partition handler and thus
2399
2425
    to ensure we have correct statistics we call info from open after
2448
2474
  handler **file;
2449
2475
  DBUG_ENTER("ha_partition::close");
2450
2476
 
 
2477
  DBUG_ASSERT(table->s == table_share);
2451
2478
  delete_queue(&m_queue);
2452
2479
  if (!is_clone)
2453
2480
    bitmap_free(&(m_part_info->used_partitions));
2516
2543
  handler **file;
2517
2544
  DBUG_ENTER("ha_partition::external_lock");
2518
2545
 
 
2546
  DBUG_ASSERT(!auto_increment_lock && !auto_increment_safe_stmt_log_lock);
2519
2547
  file= m_file;
2520
2548
  m_lock_type= lock_type;
2521
2549
 
2734
2762
  uint32 part_id;
2735
2763
  int error;
2736
2764
  longlong func_value;
2737
 
  bool autoincrement_lock= FALSE;
 
2765
  bool have_auto_increment= table->next_number_field && buf == table->record[0];
2738
2766
  my_bitmap_map *old_map;
 
2767
  HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
2739
2768
  THD *thd= ha_thd();
2740
2769
#ifdef NOT_NEEDED
2741
2770
  uchar *rec0= m_rec0;
2751
2780
    If we have an auto_increment column and we are writing a changed row
2752
2781
    or a new row, then update the auto_increment value in the record.
2753
2782
  */
2754
 
  if (table->next_number_field && buf == table->record[0])
 
2783
  if (have_auto_increment)
2755
2784
  {
2756
 
    /*
2757
 
      Some engines (InnoDB for example) can change autoincrement
2758
 
      counter only after 'table->write_row' operation.
2759
 
      So if another thread gets inside the ha_partition::write_row
2760
 
      before it is complete, it gets same auto_increment value,
2761
 
      which means DUP_KEY error (bug #27405)
2762
 
      Here we separate the access using table_share->mutex, and
2763
 
      use autoincrement_lock variable to avoid unnecessary locks.
2764
 
      Probably not an ideal solution.
2765
 
    */
2766
 
    if (table_share->tmp_table == NO_TMP_TABLE && m_innodb)
 
2785
    if (!ha_data->auto_inc_initialized &&
 
2786
        !table->s->next_number_keypart)
2767
2787
    {
2768
2788
      /*
2769
 
        Bug#30878 crash when alter table from non partitioned table
2770
 
        to partitioned.
2771
 
        Checking if tmp table then there is no need to lock,
2772
 
        and the table_share->mutex may not be initialised.
 
2789
        If auto_increment in table_share is not initialized, start by
 
2790
        initializing it.
2773
2791
      */
2774
 
      autoincrement_lock= TRUE;
2775
 
      pthread_mutex_lock(&table_share->mutex);
 
2792
      info(HA_STATUS_AUTO);
2776
2793
    }
2777
2794
    error= update_auto_increment();
2778
 
 
2779
2795
    /*
2780
2796
      If we have failed to set the auto-increment value for this row,
2781
2797
      it is highly likely that we will not be able to insert it into
2810
2826
  DBUG_PRINT("info", ("Insert in partition %d", part_id));
2811
2827
  tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */
2812
2828
  error= m_file[part_id]->ha_write_row(buf);
 
2829
  if (have_auto_increment && !table->s->next_number_keypart)
 
2830
    set_auto_increment_if_higher();
2813
2831
  reenable_binlog(thd);
2814
2832
exit:
2815
 
  if (autoincrement_lock)
2816
 
    pthread_mutex_unlock(&table_share->mutex);
2817
2833
  DBUG_RETURN(error);
2818
2834
}
2819
2835
 
2877
2893
    goto exit;
2878
2894
  }
2879
2895
 
2880
 
  /*
2881
 
    TODO:
2882
 
      set_internal_auto_increment=
2883
 
        max(set_internal_auto_increment, new_data->auto_increment)
2884
 
  */
2885
2896
  m_last_part= new_part_id;
2886
2897
  if (new_part_id == old_part_id)
2887
2898
  {
2888
2899
    DBUG_PRINT("info", ("Update in partition %d", new_part_id));
2889
2900
    tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */
2890
2901
    error= m_file[new_part_id]->ha_update_row(old_data, new_data);
 
2902
    /*
 
2903
      if updating an auto_increment column, update
 
2904
      table_share->ha_data->next_auto_inc_val if needed.
 
2905
      (not to be used if auto_increment on secondary field in a multi-
 
2906
      column index)
 
2907
    */
 
2908
    if (table->next_number_field && new_data == table->record[0] &&
 
2909
        !table->s->next_number_keypart)
 
2910
      set_auto_increment_if_higher();
2891
2911
    reenable_binlog(thd);
2892
2912
    goto exit;
2893
2913
  }
2992
3012
{
2993
3013
  int error;
2994
3014
  handler **file;
 
3015
  THD *thd= ha_thd();
2995
3016
  DBUG_ENTER("ha_partition::delete_all_rows");
2996
3017
 
 
3018
  if (thd->lex->sql_command == SQLCOM_TRUNCATE)
 
3019
  {
 
3020
    HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
 
3021
    lock_auto_increment();
 
3022
    ha_data->next_auto_inc_val= 0;
 
3023
    ha_data->auto_inc_initialized= FALSE;
 
3024
    unlock_auto_increment();
 
3025
  }
2997
3026
  file= m_file;
2998
3027
  do
2999
3028
  {
3038
3067
 
3039
3068
  SYNOPSIS
3040
3069
    end_bulk_insert()
 
3070
    abort               1 if table will be deleted (error condition)
3041
3071
 
3042
3072
  RETURN VALUE
3043
3073
    >0                      Error code
3044
3074
    0                       Success
3045
3075
*/
3046
3076
 
3047
 
int ha_partition::end_bulk_insert()
 
3077
int ha_partition::end_bulk_insert(bool abort)
3048
3078
{
3049
3079
  int error= 0;
3050
3080
  handler **file;
3054
3084
  do
3055
3085
  {
3056
3086
    int tmp;
3057
 
    if ((tmp= (*file)->ha_end_bulk_insert()))
 
3087
    if ((tmp= (*file)->ha_end_bulk_insert(abort)))
3058
3088
      error= tmp;
3059
3089
  } while (*(++file));
3060
3090
  DBUG_RETURN(error);
3126
3156
  }
3127
3157
 
3128
3158
  /* Now we see what the index of our first important partition is */
3129
 
  DBUG_PRINT("info", ("m_part_info->used_partitions: 0x%lx",
3130
 
                      (long) m_part_info->used_partitions.bitmap));
 
3159
  DBUG_PRINT("info", ("m_part_info->used_partitions: %p",
 
3160
                      m_part_info->used_partitions.bitmap));
3131
3161
  part_id= bitmap_get_first_set(&(m_part_info->used_partitions));
3132
3162
  DBUG_PRINT("info", ("m_part_spec.start_part %d", part_id));
3133
3163
 
3297
3327
      result= HA_ERR_END_OF_FILE;
3298
3328
      break;
3299
3329
    }
 
3330
    m_last_part= part_id;
 
3331
    m_part_spec.start_part= part_id;
3300
3332
    file= m_file[part_id];
3301
3333
    DBUG_PRINT("info", ("rnd_init on partition %d", part_id));
3302
3334
    if ((result= file->ha_rnd_init(1)))
4503
4535
 
4504
4536
int ha_partition::info(uint flag)
4505
4537
{
4506
 
  handler *file, **file_array;
4507
 
  DBUG_ENTER("ha_partition:info");
 
4538
  DBUG_ENTER("ha_partition::info");
4508
4539
 
4509
4540
  if (flag & HA_STATUS_AUTO)
4510
4541
  {
4511
 
    ulonglong auto_increment_value= 0;
 
4542
    bool auto_inc_is_first_in_idx= (table_share->next_number_keypart == 0);
 
4543
    HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
4512
4544
    DBUG_PRINT("info", ("HA_STATUS_AUTO"));
4513
 
    file_array= m_file;
4514
 
    do
4515
 
    {
4516
 
      file= *file_array;
4517
 
      file->info(HA_STATUS_AUTO);
4518
 
      set_if_bigger(auto_increment_value, file->stats.auto_increment_value);
4519
 
    } while (*(++file_array));
4520
 
    stats.auto_increment_value= auto_increment_value;
 
4545
    if (!table->found_next_number_field)
 
4546
      stats.auto_increment_value= 0;
 
4547
    else if (ha_data->auto_inc_initialized)
 
4548
    {
 
4549
      lock_auto_increment();
 
4550
      stats.auto_increment_value= ha_data->next_auto_inc_val;
 
4551
      unlock_auto_increment();
 
4552
    }
 
4553
    else
 
4554
    {
 
4555
      lock_auto_increment();
 
4556
      /* to avoid two concurrent initializations, check again when locked */
 
4557
      if (ha_data->auto_inc_initialized)
 
4558
        stats.auto_increment_value= ha_data->next_auto_inc_val;
 
4559
      else
 
4560
      {
 
4561
        handler *file, **file_array;
 
4562
        ulonglong auto_increment_value= 0;
 
4563
        file_array= m_file;
 
4564
        DBUG_PRINT("info",
 
4565
                   ("checking all partitions for auto_increment_value"));
 
4566
        do
 
4567
        {
 
4568
          file= *file_array;
 
4569
          file->info(HA_STATUS_AUTO);
 
4570
          set_if_bigger(auto_increment_value,
 
4571
                        file->stats.auto_increment_value);
 
4572
        } while (*(++file_array));
 
4573
 
 
4574
        DBUG_ASSERT(auto_increment_value);
 
4575
        stats.auto_increment_value= auto_increment_value;
 
4576
        if (auto_inc_is_first_in_idx)
 
4577
        {
 
4578
          set_if_bigger(ha_data->next_auto_inc_val, auto_increment_value);
 
4579
          ha_data->auto_inc_initialized= TRUE;
 
4580
          DBUG_PRINT("info", ("initializing next_auto_inc_val to %lu",
 
4581
                              (ulong) ha_data->next_auto_inc_val));
 
4582
        }
 
4583
      }
 
4584
      unlock_auto_increment();
 
4585
    }
4521
4586
  }
4522
4587
  if (flag & HA_STATUS_VARIABLE)
4523
4588
  {
4541
4606
      check_time:        Time of last check (only applicable to MyISAM)
4542
4607
      We report last time of all underlying handlers
4543
4608
    */
 
4609
    handler *file, **file_array;
4544
4610
    stats.records= 0;
4545
4611
    stats.deleted= 0;
4546
4612
    stats.data_file_length= 0;
4622
4688
      So we calculate these constants by using the variables on the first
4623
4689
      handler.
4624
4690
    */
 
4691
    handler *file;
4625
4692
 
4626
4693
    file= m_file[0];
4627
4694
    file->info(HA_STATUS_CONST);
4643
4710
  }
4644
4711
  if (flag & HA_STATUS_TIME)
4645
4712
  {
 
4713
    handler *file, **file_array;
4646
4714
    DBUG_PRINT("info", ("info: HA_STATUS_TIME"));
4647
4715
    /*
4648
4716
      This flag is used to set the latest update time of the table.
4680
4748
  stat_info->update_time=          file->stats.update_time;
4681
4749
  stat_info->check_time=           file->stats.check_time;
4682
4750
  stat_info->check_sum= 0;
4683
 
  if (file->ha_table_flags() & HA_HAS_CHECKSUM)
 
4751
  if (file->ha_table_flags() & (HA_HAS_OLD_CHECKSUM | HA_HAS_NEW_CHECKSUM))
4684
4752
    stat_info->check_sum= file->checksum();
4685
4753
  return;
4686
4754
}
4687
4755
 
4688
4756
 
4689
 
/*
4690
 
  General function to prepare handler for certain behavior
 
4757
/**
 
4758
  General function to prepare handler for certain behavior.
4691
4759
 
4692
 
  SYNOPSIS
4693
 
    extra()
 
4760
  @param[in]    operation       operation to execute
4694
4761
    operation              Operation type for extra call
4695
4762
 
4696
 
  RETURN VALUE
4697
 
    >0                     Error code
4698
 
    0                      Success
4699
 
 
4700
 
  DESCRIPTION
 
4763
  @return       status
 
4764
    @retval     0               success
 
4765
    @retval     >0              error code
 
4766
 
 
4767
  @detail
 
4768
 
4701
4769
  extra() is called whenever the server wishes to send a hint to
4702
4770
  the storage engine. The MyISAM engine implements the most hints.
4703
4771
 
4704
4772
  We divide the parameters into the following categories:
4705
 
  1) Parameters used by most handlers
4706
 
  2) Parameters used by some non-MyISAM handlers
4707
 
  3) Parameters used only by MyISAM
4708
 
  4) Parameters only used by temporary tables for query processing
4709
 
  5) Parameters only used by MyISAM internally
4710
 
  6) Parameters not used at all
4711
 
  7) Parameters only used by federated tables for query processing
4712
 
  8) Parameters only used by NDB
 
4773
  1) Operations used by most handlers
 
4774
  2) Operations used by some non-MyISAM handlers
 
4775
  3) Operations used only by MyISAM
 
4776
  4) Operations only used by temporary tables for query processing
 
4777
  5) Operations only used by MyISAM internally
 
4778
  6) Operations not used at all
 
4779
  7) Operations only used by federated tables for query processing
 
4780
  8) Operations only used by NDB
 
4781
  9) Operations only used by MERGE
4713
4782
 
4714
4783
  The partition handler need to handle category 1), 2) and 3).
4715
4784
 
4716
 
  1) Parameters used by most handlers
 
4785
  1) Operations used by most handlers
4717
4786
  -----------------------------------
4718
4787
  HA_EXTRA_RESET:
4719
4788
    This option is used by most handlers and it resets the handler state
4752
4821
    ensure disk based tables are flushed at end of query execution.
4753
4822
    Currently is never used.
4754
4823
 
4755
 
  2) Parameters used by some non-MyISAM handlers
 
4824
  2) Operations used by some non-MyISAM handlers
4756
4825
  ----------------------------------------------
4757
4826
  HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
4758
4827
    This is a strictly InnoDB feature that is more or less undocumented.
4771
4840
    SQL constructs.
4772
4841
    Not used by MyISAM.
4773
4842
 
4774
 
  3) Parameters used only by MyISAM
 
4843
  3) Operations used only by MyISAM
4775
4844
  ---------------------------------
4776
4845
  HA_EXTRA_NORMAL:
4777
4846
    Only used in MyISAM to reset quick mode, not implemented by any other
4871
4940
    about this call). We pass this along to all underlying MyISAM handlers
4872
4941
    and ignore it for the rest.
4873
4942
 
4874
 
  HA_EXTRA_PREPARE_FOR_DELETE:
 
4943
  HA_EXTRA_PREPARE_FOR_DROP:
4875
4944
    Only used by MyISAM, called in preparation for a DROP TABLE.
4876
4945
    It's used mostly by Windows that cannot handle dropping an open file.
4877
4946
    On other platforms it has the same effect as HA_EXTRA_FORCE_REOPEN.
4878
4947
 
 
4948
  HA_EXTRA_PREPARE_FOR_RENAME:
 
4949
    Informs the handler we are about to attempt a rename of the table.
 
4950
 
4879
4951
  HA_EXTRA_READCHECK:
4880
4952
  HA_EXTRA_NO_READCHECK:
4881
4953
    Only one call to HA_EXTRA_NO_READCHECK from ha_open where it says that
4899
4971
    Only used by MyISAM, called when altering table, closing tables to
4900
4972
    enforce a reopen of the table files.
4901
4973
 
4902
 
  4) Parameters only used by temporary tables for query processing
 
4974
  4) Operations only used by temporary tables for query processing
4903
4975
  ----------------------------------------------------------------
4904
4976
  HA_EXTRA_RESET_STATE:
4905
4977
    Same as reset() except that buffers are not released. If there is
4930
5002
    tables used in query processing.
4931
5003
    Not handled by partition handler.
4932
5004
 
4933
 
  5) Parameters only used by MyISAM internally
 
5005
  5) Operations only used by MyISAM internally
4934
5006
  --------------------------------------------
4935
5007
  HA_EXTRA_REINIT_CACHE:
4936
5008
    This call reinitialises the READ CACHE described above if there is one
4965
5037
  HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
4966
5038
    Only used by MyISAM, never called.
4967
5039
 
4968
 
  6) Parameters not used at all
 
5040
  6) Operations not used at all
4969
5041
  -----------------------------
4970
5042
  HA_EXTRA_KEY_CACHE:
4971
5043
  HA_EXTRA_NO_KEY_CACHE:
4972
5044
    This parameters are no longer used and could be removed.
4973
5045
 
4974
 
  7) Parameters only used by federated tables for query processing
 
5046
  7) Operations only used by federated tables for query processing
4975
5047
  ----------------------------------------------------------------
4976
5048
  HA_EXTRA_INSERT_WITH_UPDATE:
4977
5049
    Inform handler that an "INSERT...ON DUPLICATE KEY UPDATE" will be
4978
5050
    executed. This condition is unset by HA_EXTRA_NO_IGNORE_DUP_KEY.
4979
5051
 
4980
 
  8) Parameters only used by NDB
 
5052
  8) Operations only used by NDB
4981
5053
  ------------------------------
4982
5054
  HA_EXTRA_DELETE_CANNOT_BATCH:
4983
5055
  HA_EXTRA_UPDATE_CANNOT_BATCH:
4985
5057
    and should perform them immediately. This may be needed when table has 
4986
5058
    AFTER DELETE/UPDATE triggers which access to subject table.
4987
5059
    These flags are reset by the handler::extra(HA_EXTRA_RESET) call.
 
5060
 
 
5061
  9) Operations only used by MERGE
 
5062
  ------------------------------
 
5063
  HA_EXTRA_ADD_CHILDREN_LIST:
 
5064
  HA_EXTRA_ATTACH_CHILDREN:
 
5065
  HA_EXTRA_IS_ATTACHED_CHILDREN:
 
5066
  HA_EXTRA_DETACH_CHILDREN:
 
5067
    Special actions for MERGE tables. Ignore.
4988
5068
*/
4989
5069
 
4990
5070
int ha_partition::extra(enum ha_extra_function operation)
5010
5090
  }
5011
5091
 
5012
5092
  /* Category 3), used by MyISAM handlers */
5013
 
  case HA_EXTRA_PREPARE_FOR_DELETE:
5014
 
    DBUG_RETURN(prepare_for_delete());
5015
 
    break;
 
5093
  case HA_EXTRA_PREPARE_FOR_RENAME:
 
5094
    DBUG_RETURN(prepare_for_rename());
5016
5095
  case HA_EXTRA_NORMAL:
5017
5096
  case HA_EXTRA_QUICK:
5018
5097
  case HA_EXTRA_NO_READCHECK:
5019
5098
  case HA_EXTRA_PREPARE_FOR_UPDATE:
5020
5099
  case HA_EXTRA_FORCE_REOPEN:
 
5100
  case HA_EXTRA_PREPARE_FOR_DROP:
5021
5101
  case HA_EXTRA_FLUSH_CACHE:
5022
5102
  {
5023
5103
    if (m_myisam)
5069
5149
    /* Category 7), used by federated handlers */
5070
5150
  case HA_EXTRA_INSERT_WITH_UPDATE:
5071
5151
    DBUG_RETURN(loop_extra(operation));
5072
 
    /* Category 8) Parameters only used by NDB */
 
5152
    /* Category 8) Operations only used by NDB */
5073
5153
  case HA_EXTRA_DELETE_CANNOT_BATCH:
5074
5154
  case HA_EXTRA_UPDATE_CANNOT_BATCH:
5075
 
  {
5076
5155
    /* Currently only NDB use the *_CANNOT_BATCH */
 
5156
  {
 
5157
    break;
 
5158
  }
 
5159
  case HA_EXTRA_ORDERBY_LIMIT:
 
5160
  case HA_EXTRA_NO_ORDERBY_LIMIT:
 
5161
    /* ORDERBY_LIMIT is used by Falcon */
 
5162
  {
 
5163
    break;
 
5164
  }
 
5165
    /* Category 9) Operations only used by MERGE */
 
5166
  case HA_EXTRA_ADD_CHILDREN_LIST:
 
5167
  case HA_EXTRA_ATTACH_CHILDREN:
 
5168
  case HA_EXTRA_IS_ATTACHED_CHILDREN:
 
5169
  case HA_EXTRA_DETACH_CHILDREN:
 
5170
  {
 
5171
    /* Special actions for MERGE tables. Ignore. */
5077
5172
    break;
5078
5173
  }
5079
5174
  default:
5176
5271
    0                     Success
5177
5272
*/
5178
5273
 
5179
 
int ha_partition::prepare_for_delete()
 
5274
int ha_partition::prepare_for_rename()
5180
5275
{
5181
5276
  int result= 0, tmp;
5182
5277
  handler **file;
5183
 
  DBUG_ENTER("ha_partition::prepare_for_delete()");
 
5278
  DBUG_ENTER("ha_partition::prepare_for_rename()");
5184
5279
  
5185
5280
  if (m_new_file != NULL)
5186
5281
  {
5187
5282
    for (file= m_new_file; *file; file++)
5188
 
      if ((tmp= (*file)->extra(HA_EXTRA_PREPARE_FOR_DELETE)))
 
5283
      if ((tmp= (*file)->extra(HA_EXTRA_PREPARE_FOR_RENAME)))
5189
5284
        result= tmp;      
5190
5285
    for (file= m_reorged_file; *file; file++)
5191
 
      if ((tmp= (*file)->extra(HA_EXTRA_PREPARE_FOR_DELETE)))
 
5286
      if ((tmp= (*file)->extra(HA_EXTRA_PREPARE_FOR_RENAME)))
5192
5287
        result= tmp;   
5193
5288
    DBUG_RETURN(result);   
5194
5289
  }
5195
5290
  
5196
 
  DBUG_RETURN(loop_extra(HA_EXTRA_PREPARE_FOR_DELETE));
 
5291
  DBUG_RETURN(loop_extra(HA_EXTRA_PREPARE_FOR_RENAME));
5197
5292
}
5198
5293
 
5199
5294
/*
5247
5342
    DBUG_VOID_RETURN;
5248
5343
  file= m_file[partition_id];
5249
5344
  if (m_extra_cache_size == 0)
5250
 
    VOID(file->extra(HA_EXTRA_CACHE));
 
5345
    (void) file->extra(HA_EXTRA_CACHE);
5251
5346
  else
5252
 
    VOID(file->extra_opt(HA_EXTRA_CACHE, m_extra_cache_size));
 
5347
    (void) file->extra_opt(HA_EXTRA_CACHE, m_extra_cache_size);
5253
5348
  DBUG_VOID_RETURN;
5254
5349
}
5255
5350
 
5273
5368
  if (!m_extra_cache)
5274
5369
    DBUG_VOID_RETURN;
5275
5370
  file= m_file[partition_id];
5276
 
  VOID(file->extra(HA_EXTRA_NO_CACHE));
 
5371
  (void) file->extra(HA_EXTRA_NO_CACHE);
5277
5372
  DBUG_VOID_RETURN;
5278
5373
}
5279
5374
 
5426
5521
}
5427
5522
 
5428
5523
 
 
5524
/**
 
5525
  Number of rows in table. see handler.h
 
5526
 
 
5527
  SYNOPSIS
 
5528
    records()
 
5529
 
 
5530
  RETURN VALUE
 
5531
    Number of total rows in a partitioned table.
 
5532
*/
 
5533
 
 
5534
ha_rows ha_partition::records()
 
5535
{
 
5536
  ha_rows rows, tot_rows= 0;
 
5537
  handler **file;
 
5538
  DBUG_ENTER("ha_partition::records");
 
5539
 
 
5540
  file= m_file;
 
5541
  do
 
5542
  {
 
5543
    rows= (*file)->records();
 
5544
    if (rows == HA_POS_ERROR)
 
5545
      DBUG_RETURN(HA_POS_ERROR);
 
5546
    tot_rows+= rows;
 
5547
  } while (*(++file));
 
5548
  DBUG_RETURN(tot_rows);
 
5549
}
 
5550
 
 
5551
 
5429
5552
/*
5430
5553
  Is it ok to switch to a new engine for this table
5431
5554
 
5700
5823
                MODULE auto increment
5701
5824
****************************************************************************/
5702
5825
 
5703
 
void ha_partition::restore_auto_increment(ulonglong)
 
5826
 
 
5827
int ha_partition::reset_auto_increment(ulonglong value)
5704
5828
{
5705
 
  DBUG_ENTER("ha_partition::restore_auto_increment");
5706
 
 
5707
 
  DBUG_VOID_RETURN;
 
5829
  handler **file= m_file;
 
5830
  int res;
 
5831
  HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
 
5832
  DBUG_ENTER("ha_partition::reset_auto_increment");
 
5833
  lock_auto_increment();
 
5834
  ha_data->auto_inc_initialized= FALSE;
 
5835
  ha_data->next_auto_inc_val= 0;
 
5836
  do
 
5837
  {
 
5838
    if ((res= (*file)->ha_reset_auto_increment(value)) != 0)
 
5839
      break;
 
5840
  } while (*(++file));
 
5841
  unlock_auto_increment();
 
5842
  DBUG_RETURN(res);
5708
5843
}
5709
5844
 
5710
5845
 
5711
 
/*
 
5846
/**
5712
5847
  This method is called by update_auto_increment which in turn is called
5713
 
  by the individual handlers as part of write_row. We will always let
5714
 
  the first handler keep track of the auto increment value for all
5715
 
  partitions.
 
5848
  by the individual handlers as part of write_row. We use the
 
5849
  table_share->ha_data->next_auto_inc_val, or search all
 
5850
  partitions for the highest auto_increment_value if not initialized or
 
5851
  if auto_increment field is a secondary part of a key, we must search
 
5852
  every partition when holding a mutex to be sure of correctness.
5716
5853
*/
5717
5854
 
5718
5855
void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment,
5720
5857
                                      ulonglong *first_value,
5721
5858
                                      ulonglong *nb_reserved_values)
5722
5859
{
5723
 
  ulonglong first_value_part, last_value_part, nb_reserved_values_part,
5724
 
    last_value= ~ (ulonglong) 0;
5725
 
  handler **pos, **end;
5726
 
  bool retry= TRUE;
5727
5860
  DBUG_ENTER("ha_partition::get_auto_increment");
5728
 
 
5729
 
again:
5730
 
  for (pos=m_file, end= m_file+ m_tot_parts; pos != end ; pos++)
5731
 
  {
5732
 
    first_value_part= *first_value;
5733
 
    (*pos)->get_auto_increment(offset, increment, nb_desired_values,
5734
 
                               &first_value_part, &nb_reserved_values_part);
5735
 
    if (first_value_part == ~(ulonglong)(0)) // error in one partition
5736
 
    {
5737
 
      *first_value= first_value_part;
5738
 
      sql_print_error("Partition failed to reserve auto_increment value");
5739
 
      DBUG_VOID_RETURN;
5740
 
    }
5741
 
    /*
5742
 
      Partition has reserved an interval. Intersect it with the intervals
5743
 
      already reserved for the previous partitions.
5744
 
    */
5745
 
    last_value_part= (nb_reserved_values_part == ULONGLONG_MAX) ?
5746
 
      ULONGLONG_MAX : (first_value_part + nb_reserved_values_part * increment);
5747
 
    set_if_bigger(*first_value, first_value_part);
5748
 
    set_if_smaller(last_value, last_value_part);
5749
 
  }
5750
 
  if (last_value < *first_value) /* empty intersection, error */
5751
 
  {
5752
 
    /*
5753
 
      When we have an empty intersection, it means that one or more
5754
 
      partitions may have a significantly different autoinc next value.
5755
 
      We should not fail here - it just means that we should try to
5756
 
      find a new reservation making use of the current *first_value
5757
 
      wbich should now be compatible with all partitions.
5758
 
    */
5759
 
    if (retry)
5760
 
    {
5761
 
      retry= FALSE;
5762
 
      last_value= ~ (ulonglong) 0;
5763
 
      release_auto_increment();
5764
 
      goto again;
5765
 
    }
5766
 
    /*
5767
 
      We should not get here.
5768
 
    */
5769
 
    sql_print_error("Failed to calculate auto_increment value for partition");
5770
 
    
5771
 
    *first_value= ~(ulonglong)(0);
5772
 
  }
5773
 
  if (increment)                                // If not check for values
5774
 
    *nb_reserved_values= (last_value == ULONGLONG_MAX) ?
5775
 
      ULONGLONG_MAX : ((last_value - *first_value) / increment);
 
5861
  DBUG_PRINT("info", ("offset: %lu inc: %lu desired_values: %lu "
 
5862
                      "first_value: %lu", (ulong) offset, (ulong) increment,
 
5863
                      (ulong) nb_desired_values, (ulong) *first_value));
 
5864
  DBUG_ASSERT(increment && nb_desired_values);
 
5865
  *first_value= 0;
 
5866
  if (table->s->next_number_keypart)
 
5867
  {
 
5868
    /*
 
5869
      next_number_keypart is != 0 if the auto_increment column is a secondary
 
5870
      column in the index (it is allowed in MyISAM)
 
5871
    */
 
5872
    DBUG_PRINT("info", ("next_number_keypart != 0"));
 
5873
    ulonglong nb_reserved_values_part;
 
5874
    ulonglong first_value_part, max_first_value;
 
5875
    handler **file= m_file;
 
5876
    first_value_part= max_first_value= *first_value;
 
5877
    /* Must lock and find highest value among all partitions. */
 
5878
    lock_auto_increment();
 
5879
    do
 
5880
    {
 
5881
      /* Only nb_desired_values = 1 makes sense */
 
5882
      (*file)->get_auto_increment(offset, increment, 1,
 
5883
                                 &first_value_part, &nb_reserved_values_part);
 
5884
      if (first_value_part == ~(ulonglong)(0)) // error in one partition
 
5885
      {
 
5886
        *first_value= first_value_part;
 
5887
        sql_print_error("Partition failed to reserve auto_increment value");
 
5888
        unlock_auto_increment();
 
5889
        DBUG_VOID_RETURN;
 
5890
      }
 
5891
      DBUG_PRINT("info", ("first_value_part: %lu", (ulong) first_value_part));
 
5892
      set_if_bigger(max_first_value, first_value_part);
 
5893
    } while (*(++file));
 
5894
    *first_value= max_first_value;
 
5895
    *nb_reserved_values= 1;
 
5896
    unlock_auto_increment();
 
5897
  }
 
5898
  else
 
5899
  {
 
5900
    THD *thd= ha_thd();
 
5901
    HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
 
5902
    /*
 
5903
      This is initialized in the beginning of the first write_row call.
 
5904
    */
 
5905
    DBUG_ASSERT(ha_data->auto_inc_initialized);
 
5906
    /*
 
5907
      Get a lock for handling the auto_increment in table_share->ha_data
 
5908
      for avoiding two concurrent statements getting the same number.
 
5909
    */ 
 
5910
 
 
5911
    lock_auto_increment();
 
5912
 
 
5913
    /*
 
5914
      In a multi-row insert statement like INSERT SELECT and LOAD DATA
 
5915
      where the number of candidate rows to insert is not known in advance
 
5916
      we must hold a lock/mutex for the whole statement if we have statement
 
5917
      based replication. Because the statement-based binary log contains
 
5918
      only the first generated value used by the statement, and slaves assumes
 
5919
      all other generated values used by this statement were consecutive to
 
5920
      this first one, we must exclusively lock the generator until the statement
 
5921
      is done.
 
5922
    */
 
5923
    if (!auto_increment_safe_stmt_log_lock &&
 
5924
        thd->lex->sql_command != SQLCOM_INSERT &&
 
5925
        mysql_bin_log.is_open() &&
 
5926
        !thd->current_stmt_binlog_row_based &&
 
5927
        (thd->options & OPTION_BIN_LOG))
 
5928
    {
 
5929
      DBUG_PRINT("info", ("locking auto_increment_safe_stmt_log_lock"));
 
5930
      auto_increment_safe_stmt_log_lock= TRUE;
 
5931
    }
 
5932
 
 
5933
    /* this gets corrected (for offset/increment) in update_auto_increment */
 
5934
    *first_value= ha_data->next_auto_inc_val;
 
5935
    ha_data->next_auto_inc_val+= nb_desired_values * increment;
 
5936
 
 
5937
    unlock_auto_increment();
 
5938
    DBUG_PRINT("info", ("*first_value: %lu", (ulong) *first_value));
 
5939
    *nb_reserved_values= nb_desired_values;
 
5940
  }
5776
5941
  DBUG_VOID_RETURN;
5777
5942
}
5778
5943
 
5780
5945
{
5781
5946
  DBUG_ENTER("ha_partition::release_auto_increment");
5782
5947
 
5783
 
  for (uint i= 0; i < m_tot_parts; i++)
5784
 
  {
5785
 
    m_file[i]->ha_release_auto_increment();
 
5948
  if (table->s->next_number_keypart)
 
5949
  {
 
5950
    for (uint i= 0; i < m_tot_parts; i++)
 
5951
      m_file[i]->ha_release_auto_increment();
 
5952
  }
 
5953
  else if (next_insert_id)
 
5954
  {
 
5955
    HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
 
5956
    ulonglong next_auto_inc_val;
 
5957
    lock_auto_increment();
 
5958
    next_auto_inc_val= ha_data->next_auto_inc_val;
 
5959
    if (next_insert_id < next_auto_inc_val &&
 
5960
        auto_inc_interval_for_cur_row.maximum() >= next_auto_inc_val)
 
5961
      ha_data->next_auto_inc_val= next_insert_id;
 
5962
    DBUG_PRINT("info", ("ha_data->next_auto_inc_val: %lu",
 
5963
                        (ulong) ha_data->next_auto_inc_val));
 
5964
 
 
5965
    /* Unlock the multi row statement lock taken in get_auto_increment */
 
5966
    if (auto_increment_safe_stmt_log_lock)
 
5967
    {
 
5968
      auto_increment_safe_stmt_log_lock= FALSE;
 
5969
      DBUG_PRINT("info", ("unlocking auto_increment_safe_stmt_log_lock"));
 
5970
    }
 
5971
 
 
5972
    unlock_auto_increment();
5786
5973
  }
5787
5974
  DBUG_VOID_RETURN;
5788
5975
}
5929
6116
    if (!partition_init)
5930
6117
    {
5931
6118
      partition_init++;
5932
 
      VOID(pthread_mutex_init(&partition_mutex, MY_MUTEX_INIT_FAST));
 
6119
      pthread_mutex_init(&partition_mutex, MY_MUTEX_INIT_FAST);
5933
6120
      (void) hash_init(&partition_open_tables, system_charset_info, 32, 0, 0,
5934
6121
                       (hash_get_key) partition_get_key, 0, 0);
5935
6122
    }