1
1
/*****************************************************************************
3
Copyright (c) 2005, 2010, Innobase Oy. All Rights Reserved.
3
Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
17
17
*****************************************************************************/
19
/**************************************************//**
20
@file handler/handler0alter.cc
19
/******************************************************
22
21
*******************************************************/
23
#include <drizzled/server_includes.h>
25
24
#include <drizzled/error.h>
26
#include "drizzled/charset_info.h"
25
#include <mystrings/m_ctype.h>
27
26
#include <drizzled/field.h>
28
27
#include <drizzled/table.h>
29
28
#include <drizzled/field/varstring.h>
30
#include "drizzled/internal/my_sys.h"
33
31
#include "log0log.h"
42
40
#include "ha_innodb.h"
43
41
#include "handler0vars.h"
45
/*************************************************************//**
43
/*****************************************************************
46
44
Copies an InnoDB column to a MySQL field. This function is
47
45
adapted from row_sel_field_store_in_mysql_format(). */
50
48
innobase_col_to_mysql(
51
49
/*==================*/
52
const dict_col_t* col, /*!< in: InnoDB column */
53
const unsigned char* data, /*!< in: InnoDB column data */
54
ulint len, /*!< in: length of data, in bytes */
55
Field* field) /*!< in/out: MySQL field */
50
const dict_col_t* col, /* in: InnoDB column */
51
const unsigned char* data, /* in: InnoDB column data */
52
ulint len, /* in: length of data, in bytes */
53
Field* field) /* in/out: MySQL field */
57
55
unsigned char* ptr;
58
56
unsigned char* dest = field->ptr;
103
101
#ifdef UNIV_DEBUG
105
103
ut_ad(flen >= len);
106
ut_ad(DATA_MBMAXLEN(col->mbminmaxlen)
107
>= DATA_MBMINLEN(col->mbminmaxlen));
108
ut_ad(DATA_MBMAXLEN(col->mbminmaxlen)
109
> DATA_MBMINLEN(col->mbminmaxlen) || flen == len);
104
ut_ad(col->mbmaxlen >= col->mbminlen);
105
ut_ad(col->mbmaxlen > col->mbminlen || flen == len);
110
106
memcpy(dest, data, len);
133
/*************************************************************//**
134
Copies an InnoDB record to table->getInsertRecord(). */
129
/*****************************************************************
130
Copies an InnoDB record to table->record[0]. */
135
131
extern "C" UNIV_INTERN
137
133
innobase_rec_to_mysql(
138
134
/*==================*/
139
Table* table, /*!< in/out: MySQL table */
140
const rec_t* rec, /*!< in: record */
141
const dict_index_t* index, /*!< in: index */
142
const ulint* offsets) /*!< in: rec_get_offsets(
135
Table* table, /* in/out: MySQL table */
136
const rec_t* rec, /* in: record */
137
const dict_index_t* index, /* in: index */
138
const ulint* offsets) /* in: rec_get_offsets(
143
139
rec, index, ...) */
145
uint n_fields = table->getShare()->sizeFields();
141
uint n_fields = table->s->fields;
148
144
ut_ad(n_fields == dict_table_get_n_user_cols(index->table));
150
146
for (i = 0; i < n_fields; i++) {
151
Field* field = table->getField(i);
147
Field* field = table->field[i];
154
150
const unsigned char* ifield;
183
/*************************************************************//**
184
Resets table->getInsertRecord(). */
179
/*****************************************************************
180
Resets table->record[0]. */
185
181
extern "C" UNIV_INTERN
187
183
innobase_rec_reset(
188
184
/*===============*/
189
Table* table) /*!< in/out: MySQL table */
185
Table* table) /* in/out: MySQL table */
191
uint n_fields = table->getShare()->sizeFields();
187
uint n_fields = table->s->fields;
194
190
for (i = 0; i < n_fields; i++) {
195
table->getField(i)->set_default();
191
table->field[i]->set_default();
199
#if 0 // This is a part of the fast index code.
200
/******************************************************************//**
195
/**********************************************************************
201
196
Removes the filename encoding of a database and table name. */
204
199
innobase_convert_tablename(
205
200
/*=======================*/
206
char* s) /*!< in: identifier; out: decoded identifier */
201
char* s) /* in: identifier; out: decoded identifier */
209
204
char* slash = strchr(s, '/');
228
/*******************************************************************//**
229
This function checks that index keys are sensible.
230
@return 0 or error number */
222
/***********************************************************************
223
This function checks that index keys are sensible. */
233
226
innobase_check_index_keys(
234
227
/*======================*/
235
const KeyInfo* key_info, /*!< in: Indexes to be created */
236
ulint num_of_keys, /*!< in: Number of indexes to
228
/* out: 0 or error number */
229
const KEY* key_info, /* in: Indexes to be created */
230
ulint num_of_keys) /* in: Number of indexes to
238
const dict_table_t* table) /*!< in: Existing indexes */
243
236
ut_ad(num_of_keys);
245
238
for (key_num = 0; key_num < num_of_keys; key_num++) {
246
const KeyInfo& key = key_info[key_num];
239
const KEY& key = key_info[key_num];
248
241
/* Check that the same index name does not appear
249
242
twice in indexes to be created. */
251
244
for (ulint i = 0; i < key_num; i++) {
252
const KeyInfo& key2 = key_info[i];
245
const KEY& key2 = key_info[i];
254
247
if (0 == strcmp(key.name, key2.name)) {
255
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
258
return(ER_WRONG_NAME_FOR_INDEX);
262
/* Check that the same index name does not already exist. */
264
for (const dict_index_t* index
265
= dict_table_get_first_index(table);
266
index; index = dict_table_get_next_index(index)) {
268
if (0 == strcmp(key.name, index->name)) {
269
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
248
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: key name `%s` appears"
249
" twice in CREATE INDEX\n",
272
252
return(ER_WRONG_NAME_FOR_INDEX);
276
256
/* Check that MySQL does not try to create a column
277
257
prefix index field on an inappropriate data type and
278
that the same column does not appear twice in the index. */
258
that the same colum does not appear twice in the index. */
280
260
for (ulint i = 0; i < key.key_parts; i++) {
281
const KeyPartInfo& key_part1
261
const KEY_PART_INFO& key_part1
282
262
= key.key_part[i];
283
263
const Field* field
284
264
= key_part1.field;
309
my_error(ER_WRONG_KEY_COLUMN, MYF(0),
289
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: MySQL is trying to"
290
" create a column prefix"
292
" inappropriate data type."
311
297
return(ER_WRONG_KEY_COLUMN);
314
300
for (ulint j = 0; j < i; j++) {
315
const KeyPartInfo& key_part2
301
const KEY_PART_INFO& key_part2
316
302
= key.key_part[j];
318
304
if (strcmp(key_part1.field->field_name,
323
my_error(ER_WRONG_KEY_COLUMN, MYF(0),
324
key_part1.field->field_name);
309
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: column `%s`"
310
" is not allowed to occur"
311
" twice in index `%s`.\n",
312
key_part1.field->field_name,
325
314
return(ER_WRONG_KEY_COLUMN);
333
/*******************************************************************//**
322
/***********************************************************************
334
323
Create index field definition for key part */
337
326
innobase_create_index_field_def(
338
327
/*============================*/
339
KeyPartInfo* key_part, /*!< in: MySQL key definition */
340
mem_heap_t* heap, /*!< in: memory heap */
341
merge_index_field_t* index_field) /*!< out: index field
328
KEY_PART_INFO* key_part, /* in: MySQL key definition */
329
mem_heap_t* heap, /* in: memory heap */
330
merge_index_field_t* index_field) /* out: index field
342
331
definition for key_part */
373
/*******************************************************************//**
362
/***********************************************************************
374
363
Create index definition for key */
377
366
innobase_create_index_def(
378
367
/*======================*/
379
KeyInfo* key, /*!< in: key definition */
380
bool new_primary, /*!< in: TRUE=generating
368
KEY* key, /* in: key definition */
369
bool new_primary, /* in: TRUE=generating
381
370
a new primary key
383
bool key_primary, /*!< in: TRUE if this key
372
bool key_primary, /* in: TRUE if this key
384
373
is a primary key */
385
merge_index_def_t* index, /*!< out: index definition */
386
mem_heap_t* heap) /*!< in: heap where memory
374
merge_index_def_t* index, /* out: index definition */
375
mem_heap_t* heap) /* in: heap where memory
425
/*******************************************************************//**
414
/***********************************************************************
426
415
Copy index field definition */
429
418
innobase_copy_index_field_def(
430
419
/*==========================*/
431
const dict_field_t* field, /*!< in: definition to copy */
432
merge_index_field_t* index_field) /*!< out: copied definition */
420
const dict_field_t* field, /* in: definition to copy */
421
merge_index_field_t* index_field) /* out: copied definition */
434
423
assert(field != NULL);
435
424
assert(index_field != NULL);
443
/*******************************************************************//**
432
/***********************************************************************
444
433
Copy index definition for the index */
447
436
innobase_copy_index_def(
448
437
/*====================*/
449
const dict_index_t* index, /*!< in: index definition to copy */
450
merge_index_def_t* new_index,/*!< out: Index definition */
451
mem_heap_t* heap) /*!< in: heap where allocated */
438
const dict_index_t* index, /* in: index definition to copy */
439
merge_index_def_t* new_index,/* out: Index definition */
440
mem_heap_t* heap) /* in: heap where allocated */
479
/*******************************************************************//**
468
/***********************************************************************
480
469
Create an index table where indexes are ordered as follows:
482
471
IF a new primary key is defined for the table THEN
495
@return key definitions or NULL */
498
485
merge_index_def_t*
499
486
innobase_create_key_def(
500
487
/*====================*/
501
trx_t* trx, /*!< in: trx */
502
const dict_table_t*table, /*!< in: table definition */
503
mem_heap_t* heap, /*!< in: heap where space for key
488
/* out: key definitions or NULL */
489
trx_t* trx, /* in: trx */
490
const dict_table_t*table, /* in: table definition */
491
mem_heap_t* heap, /* in: heap where space for key
504
492
definitions are allocated */
505
KeyInfo* key_info, /*!< in: Indexes to be created */
506
ulint& n_keys) /*!< in/out: Number of indexes to
493
KEY* key_info, /* in: Indexes to be created */
494
ulint& n_keys) /* in/out: Number of indexes to
522
510
key_info->name, "PRIMARY");
524
512
/* If there is a UNIQUE INDEX consisting entirely of NOT NULL
525
columns and if the index does not contain column prefix(es)
526
(only prefix/part of the column is indexed), MySQL will treat the
527
index as a PRIMARY KEY unless the table already has one. */
513
columns, MySQL will treat it as a PRIMARY KEY unless the
514
table already has one. */
529
516
if (!new_primary && (key_info->flags & HA_NOSAME)
530
&& (!(key_info->flags & HA_KEY_HAS_PART_KEY_SEG))
531
517
&& row_table_got_default_clust_index(table)) {
532
uint key_part = key_info->key_parts;
518
uint key_part = key_info->key_parts;
534
520
new_primary = TRUE;
536
522
while (key_part--) {
537
if (key_info->key_part[key_part].null_bit == 0) {
523
if (key_info->key_part[key_part].key_type
524
& FIELDFLAG_MAYBE_NULL) {
538
525
new_primary = FALSE;
583
570
return(indexdefs);
586
/*******************************************************************//**
587
Create a temporary tablename using query id, thread id, and id
588
@return temporary tablename */
573
/***********************************************************************
574
Create a temporary tablename using query id, thread id, and id */
591
577
innobase_create_temporary_tablename(
592
578
/*================================*/
593
mem_heap_t* heap, /*!< in: memory heap */
594
char id, /*!< in: identifier [0-9a-zA-Z] */
595
const char* table_name) /*!< in: table name */
579
/* out: temporary tablename */
580
mem_heap_t* heap, /* in: memory heap */
581
char id, /* in: identifier [0-9a-zA-Z] */
582
const char* table_name) /* in: table name */
612
/*******************************************************************//**
614
@return 0 or error number */
598
/***********************************************************************
617
602
ha_innobase::add_index(
618
603
/*===================*/
620
Table* i_table, /*!< in: Table where indexes are created */
621
KeyInfo* key_info, /*!< in: Indexes to be created */
622
uint num_of_keys) /*!< in: Number of indexes to be created */
604
/* out: 0 or error number */
605
Table* i_table, /* in: Table where indexes are created */
606
KEY* key_info, /* in: Indexes to be created */
607
uint num_of_keys) /* in: Number of indexes to be created */
624
dict_index_t** index; /*!< Index to be created */
625
dict_table_t* innodb_table; /*!< InnoDB table in dictionary */
626
dict_table_t* indexed_table; /*!< Table where indexes are created */
627
merge_index_def_t* index_defs; /*!< Index definitions */
628
mem_heap_t* heap; /*!< Heap for index definitions */
629
trx_t* trx; /*!< Transaction */
609
dict_index_t** index; /* Index to be created */
610
dict_table_t* innodb_table; /* InnoDB table in dictionary */
611
dict_table_t* indexed_table; /* Table where indexes are created */
612
merge_index_def_t* index_defs; /* Index definitions */
613
mem_heap_t* heap; /* Heap for index definitions */
614
trx_t* trx; /* Transaction */
630
615
ulint num_of_idx;
631
616
ulint num_created = 0;
632
617
ibool dict_locked = FALSE;
633
618
ulint new_primary;
641
626
return(HA_ERR_WRONG_COMMAND);
644
update_session(session);
646
631
heap = mem_heap_create(1024);
648
633
/* In case MySQL calls this in the middle of a SELECT query, release
649
634
possible adaptive hash latch to avoid deadlocks of threads. */
650
635
trx_search_latch_release_if_reserved(prebuilt->trx);
651
trx_start_if_not_started(prebuilt->trx);
653
637
/* Create a background transaction for the operations on
654
638
the data dictionary tables. */
658
642
innodb_table = indexed_table
659
643
= dict_table_get(prebuilt->table->name, FALSE);
661
if (UNIV_UNLIKELY(!innodb_table)) {
662
error = HA_ERR_NO_SUCH_TABLE;
645
/* Check that index keys are sensible */
666
/* Check if the index name is reserved. */
667
if (innobase_index_name_is_reserved(trx, key_info, num_of_keys)) {
670
/* Check that index keys are sensible */
671
error = innobase_check_index_keys(key_info, num_of_keys,
647
error = innobase_check_index_keys(key_info, num_of_keys);
675
649
if (UNIV_UNLIKELY(error)) {
677
651
mem_heap_free(heap);
678
trx_general_rollback_for_mysql(trx, NULL);
652
trx_general_rollback_for_mysql(trx, FALSE, NULL);
679
653
trx_free_for_mysql(trx);
680
654
trx_commit_for_mysql(prebuilt->trx);
716
690
row_mysql_lock_data_dictionary(trx);
717
691
dict_locked = TRUE;
719
ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
721
693
/* If a new primary key is defined for the table we need
722
694
to drop the original table and rebuild all indexes. */
777
747
ut_ad(error == DB_SUCCESS);
779
/* We will need to rebuild index translation table. Set
780
valid index entry count in the translation table to zero */
781
share->idx_trans_tbl.index_count = 0;
783
749
/* Commit the data dictionary transaction in order to release
784
the table locks on the system tables. This means that if
785
MySQL crashes while creating a new primary key inside
786
row_merge_build_indexes(), indexed_table will not be dropped
787
by trx_rollback_active(). It will have to be recovered or
788
dropped by the database administrator. */
750
the table locks on the system tables. Unfortunately, this
751
means that if MySQL crashes while creating a new primary key
752
inside row_merge_build_indexes(), indexed_table will not be
753
dropped on crash recovery. Thus, it will become orphaned. */
789
754
trx_commit_for_mysql(trx);
791
756
row_mysql_unlock_data_dictionary(trx);
815
780
index, num_of_idx, i_table);
784
/* TODO: At the moment we can't handle the following statement
785
in our debugging code below:
787
alter table t drop index b, add index (b);
789
The fix will have to parse the SQL and note that the index
790
being added has the same name as the the one being dropped and
791
ignore that in the dup index check.*/
792
//dict_table_check_for_dup_indexes(prebuilt->table);
819
795
/* After an error, remove all those index definitions from the
820
796
dictionary which were defined. */
889
862
prebuilt->trx->error_info = NULL;
890
863
/* fall through */
892
trx->error_state = DB_SUCCESS;
894
865
if (new_primary) {
895
if (indexed_table != innodb_table) {
896
row_merge_drop_table(trx, indexed_table);
866
row_merge_drop_table(trx, indexed_table);
899
868
if (!dict_locked) {
900
869
row_mysql_lock_data_dictionary(trx);
933
/*******************************************************************//**
934
Prepare to drop some indexes of a table.
935
@return 0 or error number */
901
/***********************************************************************
902
Prepare to drop some indexes of a table. */
938
905
ha_innobase::prepare_drop_index(
939
906
/*============================*/
941
Table* i_table, /*!< in: Table where indexes are dropped */
942
uint* key_num, /*!< in: Key nums to be dropped */
943
uint num_of_keys) /*!< in: Number of keys to be dropped */
907
/* out: 0 or error number */
908
Table* i_table, /* in: Table where indexes are dropped */
909
uint* key_num, /* in: Key nums to be dropped */
910
uint num_of_keys) /* in: Number of keys to be dropped */
961
928
/* Test and mark all the indexes to be dropped */
963
930
row_mysql_lock_data_dictionary(trx);
964
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
966
932
/* Check that none of the indexes have previously been flagged
996
962
/* Refuse to drop the clustered index. It would be
997
963
better to automatically generate a clustered index,
998
but drizzled::alter_table() will call this method only
964
but mysql_alter_table() will call this method only
999
965
after ha_innobase::add_index(). */
1001
967
if (dict_index_is_clust(index)) {
1127
1093
} while (index);
1130
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1131
1096
row_mysql_unlock_data_dictionary(trx);
1136
/*******************************************************************//**
1137
Drop the indexes that were passed to a successful prepare_drop_index().
1138
@return 0 or error number */
1101
/***********************************************************************
1102
Drop the indexes that were passed to a successful prepare_drop_index(). */
1141
1105
ha_innobase::final_drop_index(
1142
1106
/*==========================*/
1144
Table* ) /*!< in: Table where indexes are dropped */
1107
/* out: 0 or error number */
1108
Table* ) /* in: Table where indexes are dropped */
1146
dict_index_t* index; /*!< Index to be dropped */
1147
trx_t* trx; /*!< Transaction */
1110
dict_index_t* index; /* Index to be dropped */
1111
trx_t* trx; /* Transaction */
1150
1114
if (srv_created_new_raw || srv_force_recovery) {
1151
1115
return(HA_ERR_WRONG_COMMAND);
1154
update_session(session);
1156
1120
trx_search_latch_release_if_reserved(prebuilt->trx);
1157
trx_start_if_not_started(prebuilt->trx);
1159
1122
/* Create a background transaction for the operations on
1160
1123
the data dictionary tables. */
1172
1135
prebuilt->table->flags, user_session);
1174
1137
row_mysql_lock_data_dictionary(trx);
1175
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1177
1139
if (UNIV_UNLIKELY(err)) {
1209
1171
ut_a(!index->to_be_dropped);
1212
/* We will need to rebuild index translation table. Set
1213
valid index entry count in the translation table to zero */
1214
share->idx_trans_tbl.index_count = 0;
1175
dict_table_check_for_dup_indexes(prebuilt->table);
1217
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1218
1179
trx_commit_for_mysql(trx);
1219
1180
trx_commit_for_mysql(prebuilt->trx);
1220
1181
row_mysql_unlock_data_dictionary(trx);