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>
32
31
#include "log0log.h"
33
32
#include "row0merge.h"
34
33
#include "srv0srv.h"
36
35
#include "trx0roll.h"
37
36
#include "ha_prototypes.h"
38
37
#include "handler0alter.h"
40
40
#include "ha_innodb.h"
41
41
#include "handler0vars.h"
43
/*************************************************************//**
43
/*****************************************************************
44
44
Copies an InnoDB column to a MySQL field. This function is
45
45
adapted from row_sel_field_store_in_mysql_format(). */
48
48
innobase_col_to_mysql(
49
49
/*==================*/
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 */
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 */
55
55
unsigned char* ptr;
56
56
unsigned char* dest = field->ptr;
101
101
#ifdef UNIV_DEBUG
103
103
ut_ad(flen >= len);
104
ut_ad(DATA_MBMAXLEN(col->mbminmaxlen)
105
>= DATA_MBMINLEN(col->mbminmaxlen));
106
ut_ad(DATA_MBMAXLEN(col->mbminmaxlen)
107
> DATA_MBMINLEN(col->mbminmaxlen) || flen == len);
104
ut_ad(col->mbmaxlen >= col->mbminlen);
105
ut_ad(col->mbmaxlen > col->mbminlen || flen == len);
108
106
memcpy(dest, data, len);
131
/*************************************************************//**
132
Copies an InnoDB record to table->getInsertRecord(). */
129
/*****************************************************************
130
Copies an InnoDB record to table->record[0]. */
131
extern "C" UNIV_INTERN
135
133
innobase_rec_to_mysql(
136
134
/*==================*/
137
Table* table, /*!< in/out: MySQL table */
138
const rec_t* rec, /*!< in: record */
139
const dict_index_t* index, /*!< in: index */
140
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(
141
139
rec, index, ...) */
143
uint n_fields = table->getShare()->sizeFields();
141
uint n_fields = table->s->fields;
146
144
ut_ad(n_fields == dict_table_get_n_user_cols(index->table));
148
146
for (i = 0; i < n_fields; i++) {
149
Field* field = table->getField(i);
147
Field* field = table->field[i];
152
150
const unsigned char* ifield;
181
/*************************************************************//**
182
Resets table->getInsertRecord(). */
179
/*****************************************************************
180
Resets table->record[0]. */
181
extern "C" UNIV_INTERN
185
183
innobase_rec_reset(
186
184
/*===============*/
187
Table* table) /*!< in/out: MySQL table */
185
Table* table) /* in/out: MySQL table */
189
uint n_fields = table->getShare()->sizeFields();
187
uint n_fields = table->s->fields;
192
190
for (i = 0; i < n_fields; i++) {
193
table->getField(i)->set_default();
191
table->field[i]->set_default();
197
#if 0 // This is a part of the fast index code.
198
/******************************************************************//**
195
/**********************************************************************
199
196
Removes the filename encoding of a database and table name. */
202
199
innobase_convert_tablename(
203
200
/*=======================*/
204
char* s) /*!< in: identifier; out: decoded identifier */
201
char* s) /* in: identifier; out: decoded identifier */
207
204
char* slash = strchr(s, '/');
226
/*******************************************************************//**
227
This function checks that index keys are sensible.
228
@return 0 or error number */
222
/***********************************************************************
223
This function checks that index keys are sensible. */
231
226
innobase_check_index_keys(
232
227
/*======================*/
233
const KeyInfo* key_info, /*!< in: Indexes to be created */
234
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
236
const dict_table_t* table) /*!< in: Existing indexes */
241
236
ut_ad(num_of_keys);
243
238
for (key_num = 0; key_num < num_of_keys; key_num++) {
244
const KeyInfo& key = key_info[key_num];
239
const KEY& key = key_info[key_num];
246
241
/* Check that the same index name does not appear
247
242
twice in indexes to be created. */
249
244
for (ulint i = 0; i < key_num; i++) {
250
const KeyInfo& key2 = key_info[i];
245
const KEY& key2 = key_info[i];
252
247
if (0 == strcmp(key.name, key2.name)) {
253
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
256
return(ER_WRONG_NAME_FOR_INDEX);
260
/* Check that the same index name does not already exist. */
262
for (const dict_index_t* index
263
= dict_table_get_first_index(table);
264
index; index = dict_table_get_next_index(index)) {
266
if (0 == strcmp(key.name, index->name)) {
267
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",
270
252
return(ER_WRONG_NAME_FOR_INDEX);
274
256
/* Check that MySQL does not try to create a column
275
257
prefix index field on an inappropriate data type and
276
that the same column does not appear twice in the index. */
258
that the same colum does not appear twice in the index. */
278
260
for (ulint i = 0; i < key.key_parts; i++) {
279
const KeyPartInfo& key_part1
261
const KEY_PART_INFO& key_part1
280
262
= key.key_part[i];
281
263
const Field* field
282
264
= key_part1.field;
307
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."
309
297
return(ER_WRONG_KEY_COLUMN);
312
300
for (ulint j = 0; j < i; j++) {
313
const KeyPartInfo& key_part2
301
const KEY_PART_INFO& key_part2
314
302
= key.key_part[j];
316
304
if (strcmp(key_part1.field->field_name,
321
my_error(ER_WRONG_KEY_COLUMN, MYF(0),
322
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,
323
314
return(ER_WRONG_KEY_COLUMN);
331
/*******************************************************************//**
322
/***********************************************************************
332
323
Create index field definition for key part */
335
326
innobase_create_index_field_def(
336
327
/*============================*/
337
KeyPartInfo* key_part, /*!< in: MySQL key definition */
338
mem_heap_t* heap, /*!< in: memory heap */
339
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
340
331
definition for key_part */
371
/*******************************************************************//**
362
/***********************************************************************
372
363
Create index definition for key */
375
366
innobase_create_index_def(
376
367
/*======================*/
377
KeyInfo* key, /*!< in: key definition */
378
bool new_primary, /*!< in: TRUE=generating
368
KEY* key, /* in: key definition */
369
bool new_primary, /* in: TRUE=generating
379
370
a new primary key
381
bool key_primary, /*!< in: TRUE if this key
372
bool key_primary, /* in: TRUE if this key
382
373
is a primary key */
383
merge_index_def_t* index, /*!< out: index definition */
384
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
423
/*******************************************************************//**
414
/***********************************************************************
424
415
Copy index field definition */
427
418
innobase_copy_index_field_def(
428
419
/*==========================*/
429
const dict_field_t* field, /*!< in: definition to copy */
430
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 */
432
423
assert(field != NULL);
433
424
assert(index_field != NULL);
441
/*******************************************************************//**
432
/***********************************************************************
442
433
Copy index definition for the index */
445
436
innobase_copy_index_def(
446
437
/*====================*/
447
const dict_index_t* index, /*!< in: index definition to copy */
448
merge_index_def_t* new_index,/*!< out: Index definition */
449
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 */
477
/*******************************************************************//**
468
/***********************************************************************
478
469
Create an index table where indexes are ordered as follows:
480
471
IF a new primary key is defined for the table THEN
493
@return key definitions or NULL */
496
485
merge_index_def_t*
497
486
innobase_create_key_def(
498
487
/*====================*/
499
trx_t* trx, /*!< in: trx */
500
const dict_table_t*table, /*!< in: table definition */
501
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
502
492
definitions are allocated */
503
KeyInfo* key_info, /*!< in: Indexes to be created */
504
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
520
510
key_info->name, "PRIMARY");
522
512
/* If there is a UNIQUE INDEX consisting entirely of NOT NULL
523
columns and if the index does not contain column prefix(es)
524
(only prefix/part of the column is indexed), MySQL will treat the
525
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. */
527
516
if (!new_primary && (key_info->flags & HA_NOSAME)
528
&& (!(key_info->flags & HA_KEY_HAS_PART_KEY_SEG))
529
517
&& row_table_got_default_clust_index(table)) {
530
uint key_part = key_info->key_parts;
518
uint key_part = key_info->key_parts;
532
520
new_primary = TRUE;
534
522
while (key_part--) {
535
if (key_info->key_part[key_part].null_bit == 0) {
523
if (key_info->key_part[key_part].key_type
524
& FIELDFLAG_MAYBE_NULL) {
536
525
new_primary = FALSE;
581
570
return(indexdefs);
584
/*******************************************************************//**
585
Create a temporary tablename using query id, thread id, and id
586
@return temporary tablename */
573
/***********************************************************************
574
Create a temporary tablename using query id, thread id, and id */
589
577
innobase_create_temporary_tablename(
590
578
/*================================*/
591
mem_heap_t* heap, /*!< in: memory heap */
592
char id, /*!< in: identifier [0-9a-zA-Z] */
593
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 */
610
/*******************************************************************//**
612
@return 0 or error number */
598
/***********************************************************************
615
602
ha_innobase::add_index(
616
603
/*===================*/
618
Table* i_table, /*!< in: Table where indexes are created */
619
KeyInfo* key_info, /*!< in: Indexes to be created */
620
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 */
622
dict_index_t** index; /*!< Index to be created */
623
dict_table_t* innodb_table; /*!< InnoDB table in dictionary */
624
dict_table_t* indexed_table; /*!< Table where indexes are created */
625
merge_index_def_t* index_defs; /*!< Index definitions */
626
mem_heap_t* heap; /*!< Heap for index definitions */
627
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 */
628
615
ulint num_of_idx;
629
616
ulint num_created = 0;
630
617
ibool dict_locked = FALSE;
631
618
ulint new_primary;
639
626
return(HA_ERR_WRONG_COMMAND);
642
update_session(session);
644
631
heap = mem_heap_create(1024);
646
633
/* In case MySQL calls this in the middle of a SELECT query, release
647
634
possible adaptive hash latch to avoid deadlocks of threads. */
648
635
trx_search_latch_release_if_reserved(prebuilt->trx);
649
trx_start_if_not_started(prebuilt->trx);
651
637
/* Create a background transaction for the operations on
652
638
the data dictionary tables. */
656
642
innodb_table = indexed_table
657
643
= dict_table_get(prebuilt->table->name, FALSE);
659
if (UNIV_UNLIKELY(!innodb_table)) {
660
error = HA_ERR_NO_SUCH_TABLE;
645
/* Check that index keys are sensible */
664
/* Check if the index name is reserved. */
665
if (innobase_index_name_is_reserved(trx, key_info, num_of_keys)) {
668
/* Check that index keys are sensible */
669
error = innobase_check_index_keys(key_info, num_of_keys,
647
error = innobase_check_index_keys(key_info, num_of_keys);
673
649
if (UNIV_UNLIKELY(error)) {
675
651
mem_heap_free(heap);
676
trx_general_rollback_for_mysql(trx, NULL);
652
trx_general_rollback_for_mysql(trx, FALSE, NULL);
677
653
trx_free_for_mysql(trx);
678
654
trx_commit_for_mysql(prebuilt->trx);
714
690
row_mysql_lock_data_dictionary(trx);
715
691
dict_locked = TRUE;
717
ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
719
693
/* If a new primary key is defined for the table we need
720
694
to drop the original table and rebuild all indexes. */
775
747
ut_ad(error == DB_SUCCESS);
777
/* We will need to rebuild index translation table. Set
778
valid index entry count in the translation table to zero */
779
share->idx_trans_tbl.index_count = 0;
781
749
/* Commit the data dictionary transaction in order to release
782
the table locks on the system tables. This means that if
783
MySQL crashes while creating a new primary key inside
784
row_merge_build_indexes(), indexed_table will not be dropped
785
by trx_rollback_active(). It will have to be recovered or
786
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. */
787
754
trx_commit_for_mysql(trx);
789
756
row_mysql_unlock_data_dictionary(trx);
813
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);
817
795
/* After an error, remove all those index definitions from the
818
796
dictionary which were defined. */
887
862
prebuilt->trx->error_info = NULL;
888
863
/* fall through */
890
trx->error_state = DB_SUCCESS;
892
865
if (new_primary) {
893
if (indexed_table != innodb_table) {
894
row_merge_drop_table(trx, indexed_table);
866
row_merge_drop_table(trx, indexed_table);
897
868
if (!dict_locked) {
898
869
row_mysql_lock_data_dictionary(trx);
931
/*******************************************************************//**
932
Prepare to drop some indexes of a table.
933
@return 0 or error number */
901
/***********************************************************************
902
Prepare to drop some indexes of a table. */
936
905
ha_innobase::prepare_drop_index(
937
906
/*============================*/
939
Table* i_table, /*!< in: Table where indexes are dropped */
940
uint* key_num, /*!< in: Key nums to be dropped */
941
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 */
959
928
/* Test and mark all the indexes to be dropped */
961
930
row_mysql_lock_data_dictionary(trx);
962
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
964
932
/* Check that none of the indexes have previously been flagged
994
962
/* Refuse to drop the clustered index. It would be
995
963
better to automatically generate a clustered index,
996
but drizzled::alter_table() will call this method only
964
but mysql_alter_table() will call this method only
997
965
after ha_innobase::add_index(). */
999
967
if (dict_index_is_clust(index)) {
1005
973
index->to_be_dropped = TRUE;
1008
/* If FOREIGN_KEY_CHECKS = 1 you may not drop an index defined
976
/* If FOREIGN_KEY_CHECK = 1 you may not drop an index defined
1009
977
for a foreign key constraint because InnoDB requires that both
1010
tables contain indexes for the constraint. Such index can
1011
be dropped only if FOREIGN_KEY_CHECKS is set to 0.
1012
Note that CREATE INDEX id ON table does a CREATE INDEX and
1013
DROP INDEX, and we can ignore here foreign keys because a
1014
new index for the foreign key has already been created.
978
tables contain indexes for the constraint. Note that CREATE
979
INDEX id ON table does a CREATE INDEX and DROP INDEX, and we
980
can ignore here foreign keys because a new index for the
981
foreign key has already been created.
1016
983
We check for the foreign key constraints after marking the
1017
984
candidate indexes for deletion, because when we check for an
1126
1093
} while (index);
1129
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1130
1096
row_mysql_unlock_data_dictionary(trx);
1135
/*******************************************************************//**
1136
Drop the indexes that were passed to a successful prepare_drop_index().
1137
@return 0 or error number */
1101
/***********************************************************************
1102
Drop the indexes that were passed to a successful prepare_drop_index(). */
1140
1105
ha_innobase::final_drop_index(
1141
1106
/*==========================*/
1143
Table* ) /*!< in: Table where indexes are dropped */
1107
/* out: 0 or error number */
1108
Table* ) /* in: Table where indexes are dropped */
1145
dict_index_t* index; /*!< Index to be dropped */
1146
trx_t* trx; /*!< Transaction */
1110
dict_index_t* index; /* Index to be dropped */
1111
trx_t* trx; /* Transaction */
1149
1114
if (srv_created_new_raw || srv_force_recovery) {
1150
1115
return(HA_ERR_WRONG_COMMAND);
1153
update_session(session);
1155
1120
trx_search_latch_release_if_reserved(prebuilt->trx);
1156
trx_start_if_not_started(prebuilt->trx);
1158
1122
/* Create a background transaction for the operations on
1159
1123
the data dictionary tables. */
1171
1135
prebuilt->table->flags, user_session);
1173
1137
row_mysql_lock_data_dictionary(trx);
1174
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1176
1139
if (UNIV_UNLIKELY(err)) {
1208
1171
ut_a(!index->to_be_dropped);
1211
/* We will need to rebuild index translation table. Set
1212
valid index entry count in the translation table to zero */
1213
share->idx_trans_tbl.index_count = 0;
1175
dict_table_check_for_dup_indexes(prebuilt->table);
1216
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1217
1179
trx_commit_for_mysql(trx);
1218
1180
trx_commit_for_mysql(prebuilt->trx);
1219
1181
row_mysql_unlock_data_dictionary(trx);