~drizzle-trunk/drizzle/development

641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1
/*****************************************************************************
2
3
Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
4
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
8
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
16
17
*****************************************************************************/
18
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
19
/**************************************************//**
20
@file handler/handler0alter.cc
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
21
Smart ALTER TABLE
22
*******************************************************/
23
1241.9.36 by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h.
24
#include "config.h"
641.1.4 by Monty Taylor
Merged in InnoDB changes.
25
#include <drizzled/error.h>
26
#include <mystrings/m_ctype.h>
27
#include <drizzled/field.h>
28
#include <drizzled/table.h>
29
#include <drizzled/field/varstring.h>
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
30
31
extern "C" {
32
#include "log0log.h"
33
#include "row0merge.h"
34
#include "srv0srv.h"
35
#include "trx0trx.h"
36
#include "trx0roll.h"
37
#include "ha_prototypes.h"
38
#include "handler0alter.h"
39
}
40
41
#include "ha_innodb.h"
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
42
#include "handler0vars.h"
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
43
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
44
/*************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
45
Copies an InnoDB column to a MySQL field.  This function is
46
adapted from row_sel_field_store_in_mysql_format(). */
47
static
48
void
49
innobase_col_to_mysql(
50
/*==================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
51
	const dict_col_t*	col,	/*!< in: InnoDB column */
1114.1.1 by Monty Taylor
Merged InnoDB Plugin 1.0.4
52
	const unsigned char*	data,	/*!< in: InnoDB column data */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
53
	ulint			len,	/*!< in: length of data, in bytes */
54
	Field*			field)	/*!< in/out: MySQL field */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
55
{
641.1.4 by Monty Taylor
Merged in InnoDB changes.
56
	unsigned char*	ptr;
57
	unsigned char*	dest	= field->ptr;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
58
	ulint	flen	= field->pack_length();
59
60
	switch (col->mtype) {
61
	case DATA_INT:
62
		ut_ad(len == flen);
63
64
		/* Convert integer data from Innobase to little-endian
65
		format, sign bit restored to normal */
66
67
		for (ptr = dest + len; ptr != dest; ) {
68
			*--ptr = *data++;
69
		}
70
71
		if (!(field->flags & UNSIGNED_FLAG)) {
72
			((byte*) dest)[len - 1] ^= 0x80;
73
		}
74
75
		break;
76
77
	case DATA_VARCHAR:
78
	case DATA_VARMYSQL:
79
	case DATA_BINARY:
80
		field->reset();
81
641.1.4 by Monty Taylor
Merged in InnoDB changes.
82
		if (field->type() == DRIZZLE_TYPE_VARCHAR) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
83
			/* This is a >= 5.0.3 type true VARCHAR. Store the
84
			length of the data to the first byte or the first
85
			two bytes of dest. */
86
87
			dest = row_mysql_store_true_var_len(
88
				dest, len, flen - field->key_length());
89
		}
90
91
		/* Copy the actual data */
92
		memcpy(dest, data, len);
93
		break;
94
95
	case DATA_BLOB:
96
		/* Store a pointer to the BLOB buffer to dest: the BLOB was
97
		already copied to the buffer in row_sel_store_mysql_rec */
98
99
		row_mysql_store_blob_ref(dest, flen, data, len);
100
		break;
101
102
#ifdef UNIV_DEBUG
103
	case DATA_MYSQL:
104
		ut_ad(flen >= len);
105
		ut_ad(col->mbmaxlen >= col->mbminlen);
106
		ut_ad(col->mbmaxlen > col->mbminlen || flen == len);
107
		memcpy(dest, data, len);
108
		break;
109
110
	default:
111
	case DATA_SYS_CHILD:
112
	case DATA_SYS:
113
		/* These column types should never be shipped to MySQL. */
114
		ut_ad(0);
115
116
	case DATA_CHAR:
117
	case DATA_FIXBINARY:
118
	case DATA_FLOAT:
119
	case DATA_DOUBLE:
120
	case DATA_DECIMAL:
121
		/* Above are the valid column types for MySQL data. */
122
		ut_ad(flen == len);
123
#else /* UNIV_DEBUG */
124
	default:
125
#endif /* UNIV_DEBUG */
126
		memcpy(dest, data, len);
127
	}
128
}
129
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
130
/*************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
131
Copies an InnoDB record to table->record[0]. */
132
extern "C" UNIV_INTERN
133
void
134
innobase_rec_to_mysql(
135
/*==================*/
1114.1.1 by Monty Taylor
Merged InnoDB Plugin 1.0.4
136
	Table*			table,		/*!< in/out: MySQL table */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
137
	const rec_t*		rec,		/*!< in: record */
138
	const dict_index_t*	index,		/*!< in: index */
139
	const ulint*		offsets)	/*!< in: rec_get_offsets(
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
140
						rec, index, ...) */
141
{
142
	uint	n_fields	= table->s->fields;
143
	uint	i;
144
145
	ut_ad(n_fields == dict_table_get_n_user_cols(index->table));
146
147
	for (i = 0; i < n_fields; i++) {
148
		Field*		field	= table->field[i];
149
		ulint		ipos;
150
		ulint		ilen;
641.1.4 by Monty Taylor
Merged in InnoDB changes.
151
		const unsigned char*	ifield;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
152
153
		field->reset();
154
155
		ipos = dict_index_get_nth_col_pos(index, i);
156
157
		if (UNIV_UNLIKELY(ipos == ULINT_UNDEFINED)) {
158
null_field:
159
			field->set_null();
160
			continue;
161
		}
162
163
		ifield = rec_get_nth_field(rec, offsets, ipos, &ilen);
164
165
		/* Assign the NULL flag */
166
		if (ilen == UNIV_SQL_NULL) {
167
			ut_ad(field->real_maybe_null());
168
			goto null_field;
169
		}
170
171
		field->set_notnull();
172
173
		innobase_col_to_mysql(
174
			dict_field_get_col(
175
				dict_index_get_nth_field(index, ipos)),
176
			ifield, ilen, field);
177
	}
178
}
179
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
180
/*************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
181
Resets table->record[0]. */
182
extern "C" UNIV_INTERN
183
void
184
innobase_rec_reset(
185
/*===============*/
1114.1.1 by Monty Taylor
Merged InnoDB Plugin 1.0.4
186
	Table*			table)		/*!< in/out: MySQL table */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
187
{
188
	uint	n_fields	= table->s->fields;
189
	uint	i;
190
191
	for (i = 0; i < n_fields; i++) {
192
		table->field[i]->set_default();
193
	}
194
}
195
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
196
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
197
Removes the filename encoding of a database and table name. */
198
static
199
void
200
innobase_convert_tablename(
201
/*=======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
202
	char*	s)	/*!< in: identifier; out: decoded identifier */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
203
{
204
205
	char*	slash = strchr(s, '/');
206
207
	if (slash) {
208
		char*	t;
209
		/* Temporarily replace the '/' with NUL. */
210
		*slash = 0;
1054.2.12 by Monty Taylor
First pass at removing strconvert.
211
		strncpy(s, s, slash - s + 1);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
212
213
		t = s + strlen(s);
214
		ut_ad(slash >= t);
215
		/* Append a  '.' after the database name. */
216
		*t++ = '.';
217
		slash++;
218
		/* Convert the table name. */
1054.2.12 by Monty Taylor
First pass at removing strconvert.
219
		strncpy(t, slash, slash - t + strlen(slash));
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
220
	}
221
}
222
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
223
/*******************************************************************//**
224
This function checks that index keys are sensible.
225
@return	0 or error number */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
226
static
227
int
228
innobase_check_index_keys(
229
/*======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
230
	const KEY*	key_info,	/*!< in: Indexes to be created */
231
	ulint		num_of_keys)	/*!< in: Number of indexes to
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
232
					be created */
233
{
234
	ulint		key_num;
235
236
	ut_ad(key_info);
237
	ut_ad(num_of_keys);
238
239
	for (key_num = 0; key_num < num_of_keys; key_num++) {
240
		const KEY&	key = key_info[key_num];
241
242
		/* Check that the same index name does not appear
243
		twice in indexes to be created. */
244
245
		for (ulint i = 0; i < key_num; i++) {
246
			const KEY&	key2 = key_info[i];
247
248
			if (0 == strcmp(key.name, key2.name)) {
755.2.1 by Mark Atwood
replace sql_print_error etc with errmsg_print
249
				errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: key name `%s` appears"
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
250
						" twice in CREATE INDEX\n",
251
						key.name);
252
253
				return(ER_WRONG_NAME_FOR_INDEX);
254
			}
255
		}
256
257
		/* Check that MySQL does not try to create a column
258
		prefix index field on an inappropriate data type and
259
		that the same colum does not appear twice in the index. */
260
261
		for (ulint i = 0; i < key.key_parts; i++) {
262
			const KEY_PART_INFO&	key_part1
263
				= key.key_part[i];
264
			const Field*		field
265
				= key_part1.field;
266
			ibool			is_unsigned;
267
268
			switch (get_innobase_type_from_mysql_type(
269
					&is_unsigned, field)) {
270
			default:
271
				break;
272
			case DATA_INT:
273
			case DATA_FLOAT:
274
			case DATA_DOUBLE:
275
			case DATA_DECIMAL:
641.1.4 by Monty Taylor
Merged in InnoDB changes.
276
				if (field->type() == DRIZZLE_TYPE_VARCHAR) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
277
					if (key_part1.length
278
					    >= field->pack_length()
279
					    - ((Field_varstring*) field)
280
					    ->length_bytes) {
281
						break;
282
					}
283
				} else {
284
					if (key_part1.length
285
					    >= field->pack_length()) {
286
						break;
287
					}
288
				}
289
755.2.1 by Mark Atwood
replace sql_print_error etc with errmsg_print
290
				errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: MySQL is trying to"
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
291
						" create a column prefix"
292
						" index field on an"
293
						" inappropriate data type."
294
						" column `%s`,"
295
						" index `%s`.\n",
296
						field->field_name,
297
						key.name);
298
				return(ER_WRONG_KEY_COLUMN);
299
			}
300
301
			for (ulint j = 0; j < i; j++) {
302
				const KEY_PART_INFO&	key_part2
303
					= key.key_part[j];
304
305
				if (strcmp(key_part1.field->field_name,
306
					   key_part2.field->field_name)) {
307
					continue;
308
				}
309
755.2.1 by Mark Atwood
replace sql_print_error etc with errmsg_print
310
				errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: column `%s`"
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
311
						" is not allowed to occur"
312
						" twice in index `%s`.\n",
313
						key_part1.field->field_name,
314
						key.name);
315
				return(ER_WRONG_KEY_COLUMN);
316
			}
317
		}
318
	}
319
320
	return(0);
321
}
322
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
323
/*******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
324
Create index field definition for key part */
325
static
326
void
327
innobase_create_index_field_def(
328
/*============================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
329
	KEY_PART_INFO*		key_part,	/*!< in: MySQL key definition */
330
	mem_heap_t*		heap,		/*!< in: memory heap */
331
	merge_index_field_t*	index_field)	/*!< out: index field
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
332
						definition for key_part */
333
{
334
	Field*		field;
335
	ibool		is_unsigned;
336
	ulint		col_type;
337
338
	ut_ad(key_part);
339
	ut_ad(index_field);
340
341
	field = key_part->field;
342
	ut_a(field);
343
344
	col_type = get_innobase_type_from_mysql_type(&is_unsigned, field);
345
346
	if (DATA_BLOB == col_type
347
	    || (key_part->length < field->pack_length()
641.1.4 by Monty Taylor
Merged in InnoDB changes.
348
		&& field->type() != DRIZZLE_TYPE_VARCHAR)
349
	    || (field->type() == DRIZZLE_TYPE_VARCHAR
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
350
		&& key_part->length < field->pack_length()
351
			- ((Field_varstring*)field)->length_bytes)) {
352
353
		index_field->prefix_len = key_part->length;
354
	} else {
355
		index_field->prefix_len = 0;
356
	}
357
358
	index_field->field_name = mem_heap_strdup(heap, field->field_name);
359
641.1.4 by Monty Taylor
Merged in InnoDB changes.
360
	return;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
361
}
362
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
363
/*******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
364
Create index definition for key */
365
static
366
void
367
innobase_create_index_def(
368
/*======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
369
	KEY*			key,		/*!< in: key definition */
370
	bool			new_primary,	/*!< in: TRUE=generating
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
371
						a new primary key
372
						on the table */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
373
	bool			key_primary,	/*!< in: TRUE if this key
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
374
						is a primary key */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
375
	merge_index_def_t*	index,		/*!< out: index definition */
376
	mem_heap_t*		heap)		/*!< in: heap where memory
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
377
						is allocated */
378
{
379
	ulint	i;
380
	ulint	len;
381
	ulint	n_fields = key->key_parts;
382
	char*	index_name;
383
384
	index->fields = (merge_index_field_t*) mem_heap_alloc(
385
		heap, n_fields * sizeof *index->fields);
386
387
	index->ind_type = 0;
388
	index->n_fields = n_fields;
389
	len = strlen(key->name) + 1;
390
	index->name = index_name = (char*) mem_heap_alloc(heap,
391
							  len + !new_primary);
392
393
	if (UNIV_LIKELY(!new_primary)) {
394
		*index_name++ = TEMP_INDEX_PREFIX;
395
	}
396
397
	memcpy(index_name, key->name, len);
398
399
	if (key->flags & HA_NOSAME) {
400
		index->ind_type |= DICT_UNIQUE;
401
	}
402
403
	if (key_primary) {
404
		index->ind_type |= DICT_CLUSTERED;
405
	}
406
407
	for (i = 0; i < n_fields; i++) {
408
		innobase_create_index_field_def(&key->key_part[i], heap,
409
						&index->fields[i]);
410
	}
411
641.1.4 by Monty Taylor
Merged in InnoDB changes.
412
	return;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
413
}
414
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
415
/*******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
416
Copy index field definition */
417
static
418
void
419
innobase_copy_index_field_def(
420
/*==========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
421
	const dict_field_t*	field,		/*!< in: definition to copy */
422
	merge_index_field_t*	index_field)	/*!< out: copied definition */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
423
{
641.1.4 by Monty Taylor
Merged in InnoDB changes.
424
	assert(field != NULL);
425
	assert(index_field != NULL);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
426
427
	index_field->field_name = field->name;
428
	index_field->prefix_len = field->prefix_len;
429
641.1.4 by Monty Taylor
Merged in InnoDB changes.
430
	return;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
431
}
432
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
433
/*******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
434
Copy index definition for the index */
435
static
436
void
437
innobase_copy_index_def(
438
/*====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
439
	const dict_index_t*	index,	/*!< in: index definition to copy */
440
	merge_index_def_t*	new_index,/*!< out: Index definition */
441
	mem_heap_t*		heap)	/*!< in: heap where allocated */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
442
{
443
	ulint	n_fields;
444
	ulint	i;
445
446
	/* Note that we take only those fields that user defined to be
447
	in the index.  In the internal representation more colums were
448
	added and those colums are not copied .*/
449
450
	n_fields = index->n_user_defined_cols;
451
452
	new_index->fields = (merge_index_field_t*) mem_heap_alloc(
453
		heap, n_fields * sizeof *new_index->fields);
454
455
	/* When adding a PRIMARY KEY, we may convert a previous
456
	clustered index to a secondary index (UNIQUE NOT NULL). */
457
	new_index->ind_type = index->type & ~DICT_CLUSTERED;
458
	new_index->n_fields = n_fields;
459
	new_index->name = index->name;
460
461
	for (i = 0; i < n_fields; i++) {
462
		innobase_copy_index_field_def(&index->fields[i],
463
					      &new_index->fields[i]);
464
	}
465
641.1.4 by Monty Taylor
Merged in InnoDB changes.
466
	return;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
467
}
468
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
469
/*******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
470
Create an index table where indexes are ordered as follows:
471
472
IF a new primary key is defined for the table THEN
473
474
	1) New primary key
475
	2) Original secondary indexes
476
	3) New secondary indexes
477
478
ELSE
479
480
	1) All new indexes in the order they arrive from MySQL
481
482
ENDIF
483
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
484
485
@return	key definitions or NULL */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
486
static
487
merge_index_def_t*
488
innobase_create_key_def(
489
/*====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
490
	trx_t*		trx,		/*!< in: trx */
491
	const dict_table_t*table,		/*!< in: table definition */
492
	mem_heap_t*	heap,		/*!< in: heap where space for key
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
493
					definitions are allocated */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
494
	KEY*		key_info,	/*!< in: Indexes to be created */
495
	ulint&		n_keys)		/*!< in/out: Number of indexes to
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
496
					be created */
497
{
498
	ulint			i = 0;
499
	merge_index_def_t*	indexdef;
500
	merge_index_def_t*	indexdefs;
501
	bool			new_primary;
502
503
	indexdef = indexdefs = (merge_index_def_t*)
504
		mem_heap_alloc(heap, sizeof *indexdef
505
			       * (n_keys + UT_LIST_GET_LEN(table->indexes)));
506
507
	/* If there is a primary key, it is always the first index
508
	defined for the table. */
509
510
	new_primary = !my_strcasecmp(system_charset_info,
511
				     key_info->name, "PRIMARY");
512
513
	/* If there is a UNIQUE INDEX consisting entirely of NOT NULL
514
	columns, MySQL will treat it as a PRIMARY KEY unless the
515
	table already has one. */
516
517
	if (!new_primary && (key_info->flags & HA_NOSAME)
518
	    && row_table_got_default_clust_index(table)) {
519
		uint	key_part = key_info->key_parts;
520
521
		new_primary = TRUE;
522
523
		while (key_part--) {
1119.9.5 by Jay Pipes
Removes FIELDFLAG_NUMBER, f_is_num() and f_is_alpha() macros. Buh bye.
524
			if (key_info->key_part[key_part].null_bit == 0) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
525
				new_primary = FALSE;
526
				break;
527
			}
528
		}
529
	}
530
531
	if (new_primary) {
532
		const dict_index_t*	index;
533
534
		/* Create the PRIMARY key index definition */
535
		innobase_create_index_def(&key_info[i++], TRUE, TRUE,
536
					  indexdef++, heap);
537
538
		row_mysql_lock_data_dictionary(trx);
539
540
		index = dict_table_get_first_index(table);
541
542
		/* Copy the index definitions of the old table.  Skip
543
		the old clustered index if it is a generated clustered
544
		index or a PRIMARY KEY.  If the clustered index is a
545
		UNIQUE INDEX, it must be converted to a secondary index. */
546
547
		if (dict_index_get_nth_col(index, 0)->mtype == DATA_SYS
548
		    || !my_strcasecmp(system_charset_info,
549
				      index->name, "PRIMARY")) {
550
			index = dict_table_get_next_index(index);
551
		}
552
553
		while (index) {
554
			innobase_copy_index_def(index, indexdef++, heap);
555
			index = dict_table_get_next_index(index);
556
		}
557
558
		row_mysql_unlock_data_dictionary(trx);
559
	}
560
561
	/* Create definitions for added secondary indexes. */
562
563
	while (i < n_keys) {
564
		innobase_create_index_def(&key_info[i++], new_primary, FALSE,
565
					  indexdef++, heap);
566
	}
567
568
	n_keys = indexdef - indexdefs;
569
641.1.4 by Monty Taylor
Merged in InnoDB changes.
570
	return(indexdefs);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
571
}
572
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
573
/*******************************************************************//**
574
Create a temporary tablename using query id, thread id, and id
575
@return	temporary tablename */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
576
static
577
char*
578
innobase_create_temporary_tablename(
579
/*================================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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 */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
583
{
584
	char*			name;
585
	ulint			len;
586
	static const char	suffix[] = "@0023 "; /* "# " */
587
588
	len = strlen(table_name);
589
590
	name = (char*) mem_heap_alloc(heap, len + sizeof suffix);
591
	memcpy(name, table_name, len);
592
	memcpy(name + len, suffix, sizeof suffix);
593
	name[len + (sizeof suffix - 2)] = id;
594
595
	return(name);
596
}
597
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
598
/*******************************************************************//**
599
Create indexes.
600
@return	0 or error number */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
601
UNIV_INTERN
602
int
603
ha_innobase::add_index(
604
/*===================*/
1114.1.1 by Monty Taylor
Merged InnoDB Plugin 1.0.4
605
	Table*	i_table,	/*!< in: Table where indexes are created */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
606
	KEY*	key_info,	/*!< in: Indexes to be created */
607
	uint	num_of_keys)	/*!< in: Number of indexes to be created */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
608
{
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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 */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
615
	ulint		num_of_idx;
616
	ulint		num_created	= 0;
617
	ibool		dict_locked	= FALSE;
618
	ulint		new_primary;
619
	ulint		error;
620
779.3.10 by Monty Taylor
Turned on -Wshadow.
621
	ut_a(i_table);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
622
	ut_a(key_info);
623
	ut_a(num_of_keys);
624
625
	if (srv_created_new_raw || srv_force_recovery) {
641.1.4 by Monty Taylor
Merged in InnoDB changes.
626
		return(HA_ERR_WRONG_COMMAND);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
627
	}
628
641.1.4 by Monty Taylor
Merged in InnoDB changes.
629
	update_session();
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
630
631
	heap = mem_heap_create(1024);
632
633
	/* In case MySQL calls this in the middle of a SELECT query, release
634
	possible adaptive hash latch to avoid deadlocks of threads. */
635
	trx_search_latch_release_if_reserved(prebuilt->trx);
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
636
	trx_start_if_not_started(prebuilt->trx);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
637
638
	/* Create a background transaction for the operations on
639
	the data dictionary tables. */
933.1.2 by Monty Taylor
Fixed merge weirdness errors.
640
	trx = innobase_trx_allocate(user_session);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
641
	trx_start_if_not_started(trx);
642
643
	innodb_table = indexed_table
644
		= dict_table_get(prebuilt->table->name, FALSE);
645
646
	/* Check that index keys are sensible */
647
648
	error = innobase_check_index_keys(key_info, num_of_keys);
649
650
	if (UNIV_UNLIKELY(error)) {
651
err_exit:
652
		mem_heap_free(heap);
653
		trx_general_rollback_for_mysql(trx, FALSE, NULL);
654
		trx_free_for_mysql(trx);
655
		trx_commit_for_mysql(prebuilt->trx);
641.1.4 by Monty Taylor
Merged in InnoDB changes.
656
		return(error);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
657
	}
658
659
	/* Create table containing all indexes to be built in this
660
	alter table add index so that they are in the correct order
661
	in the table. */
662
663
	num_of_idx = num_of_keys;
664
665
	index_defs = innobase_create_key_def(
666
		trx, innodb_table, heap, key_info, num_of_idx);
667
668
	new_primary = DICT_CLUSTERED & index_defs[0].ind_type;
669
670
	/* Allocate memory for dictionary index definitions */
671
672
	index = (dict_index_t**) mem_heap_alloc(
673
		heap, num_of_idx * sizeof *index);
674
675
	/* Flag this transaction as a dictionary operation, so that
676
	the data dictionary will be locked in crash recovery. */
677
	trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
678
679
	/* Acquire a lock on the table before creating any indexes. */
680
	error = row_merge_lock_table(prebuilt->trx, innodb_table,
681
				     new_primary ? LOCK_X : LOCK_S);
682
683
	if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
684
685
		goto error_handling;
686
	}
687
688
	/* Latch the InnoDB data dictionary exclusively so that no deadlocks
689
	or lock waits can happen in it during an index create operation. */
690
691
	row_mysql_lock_data_dictionary(trx);
692
	dict_locked = TRUE;
693
694
	/* If a new primary key is defined for the table we need
695
	to drop the original table and rebuild all indexes. */
696
697
	if (UNIV_UNLIKELY(new_primary)) {
698
		/* This transaction should be the only one
699
		operating on the table. */
700
		ut_a(innodb_table->n_mysql_handles_opened == 1);
701
702
		char*	new_table_name = innobase_create_temporary_tablename(
703
			heap, '1', innodb_table->name);
704
705
		/* Clone the table. */
706
		trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
707
		indexed_table = row_merge_create_temporary_table(
708
			new_table_name, index_defs, innodb_table, trx);
709
710
		if (!indexed_table) {
711
712
			switch (trx->error_state) {
713
			case DB_TABLESPACE_ALREADY_EXISTS:
714
			case DB_DUPLICATE_KEY:
715
				innobase_convert_tablename(new_table_name);
716
				my_error(HA_ERR_TABLE_EXIST, MYF(0),
717
					 new_table_name);
718
				error = HA_ERR_TABLE_EXIST;
719
				break;
720
			default:
721
				error = convert_error_code_to_mysql(
722
					trx->error_state, innodb_table->flags,
641.1.4 by Monty Taylor
Merged in InnoDB changes.
723
					user_session);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
724
			}
725
726
			row_mysql_unlock_data_dictionary(trx);
727
			goto err_exit;
728
		}
729
730
		trx->table_id = indexed_table->id;
731
	}
732
733
	/* Create the indexes in SYS_INDEXES and load into dictionary. */
734
735
	for (ulint i = 0; i < num_of_idx; i++) {
736
737
		index[i] = row_merge_create_index(trx, indexed_table,
738
						  &index_defs[i]);
739
740
		if (!index[i]) {
741
			error = trx->error_state;
742
			goto error_handling;
743
		}
744
745
		num_created++;
746
	}
747
748
	ut_ad(error == DB_SUCCESS);
749
750
	/* Commit the data dictionary transaction in order to release
751
	the table locks on the system tables.  Unfortunately, this
752
	means that if MySQL crashes while creating a new primary key
753
	inside row_merge_build_indexes(), indexed_table will not be
754
	dropped on crash recovery.  Thus, it will become orphaned. */
755
	trx_commit_for_mysql(trx);
756
757
	row_mysql_unlock_data_dictionary(trx);
758
	dict_locked = FALSE;
759
760
	ut_a(trx->n_active_thrs == 0);
761
	ut_a(UT_LIST_GET_LEN(trx->signals) == 0);
762
763
	if (UNIV_UNLIKELY(new_primary)) {
764
		/* A primary key is to be built.  Acquire an exclusive
765
		table lock also on the table that is being created. */
766
		ut_ad(indexed_table != innodb_table);
767
768
		error = row_merge_lock_table(prebuilt->trx, indexed_table,
769
					     LOCK_X);
770
771
		if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
772
773
			goto error_handling;
774
		}
775
	}
776
777
	/* Read the clustered index of the table and build indexes
778
	based on this information using temporary files and merge sort. */
779
	error = row_merge_build_indexes(prebuilt->trx,
780
					innodb_table, indexed_table,
779.3.10 by Monty Taylor
Turned on -Wshadow.
781
					index, num_of_idx, i_table);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
782
783
error_handling:
784
#ifdef UNIV_DEBUG
785
	/* TODO: At the moment we can't handle the following statement
786
	in our debugging code below:
787
788
	alter table t drop index b, add index (b);
789
790
	The fix will have to parse the SQL and note that the index
791
	being added has the same name as the the one being dropped and
792
	ignore that in the dup index check.*/
793
	//dict_table_check_for_dup_indexes(prebuilt->table);
794
#endif
795
796
	/* After an error, remove all those index definitions from the
797
	dictionary which were defined. */
798
799
	switch (error) {
800
		const char*	old_name;
801
		char*		tmp_name;
802
	case DB_SUCCESS:
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
803
		ut_a(!dict_locked);
804
		row_mysql_lock_data_dictionary(trx);
805
		dict_locked = TRUE;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
806
807
		if (!new_primary) {
808
			error = row_merge_rename_indexes(trx, indexed_table);
809
810
			if (error != DB_SUCCESS) {
811
				row_merge_drop_indexes(trx, indexed_table,
812
						       index, num_created);
813
			}
814
815
			goto convert_error;
816
		}
817
818
		/* If a new primary key was defined for the table and
819
		there was no error at this point, we can now rename
820
		the old table as a temporary table, rename the new
821
		temporary table as the old table and drop the old table. */
822
		old_name = innodb_table->name;
823
		tmp_name = innobase_create_temporary_tablename(heap, '2',
824
							       old_name);
825
826
		error = row_merge_rename_tables(innodb_table, indexed_table,
827
						tmp_name, trx);
828
829
		if (error != DB_SUCCESS) {
830
831
			row_merge_drop_table(trx, indexed_table);
832
833
			switch (error) {
834
			case DB_TABLESPACE_ALREADY_EXISTS:
835
			case DB_DUPLICATE_KEY:
836
				innobase_convert_tablename(tmp_name);
837
				my_error(HA_ERR_TABLE_EXIST, MYF(0), tmp_name);
838
				error = HA_ERR_TABLE_EXIST;
839
				break;
840
			default:
841
				goto convert_error;
842
			}
843
			break;
844
		}
845
846
		trx_commit_for_mysql(prebuilt->trx);
847
		row_prebuilt_free(prebuilt, TRUE);
848
		prebuilt = row_create_prebuilt(indexed_table);
849
850
		indexed_table->n_mysql_handles_opened++;
851
852
		error = row_merge_drop_table(trx, innodb_table);
853
		goto convert_error;
854
855
	case DB_TOO_BIG_RECORD:
856
		my_error(HA_ERR_TO_BIG_ROW, MYF(0));
857
		goto error;
858
	case DB_PRIMARY_KEY_IS_NULL:
859
		my_error(ER_PRIMARY_CANT_HAVE_NULL, MYF(0));
860
		/* fall through */
861
	case DB_DUPLICATE_KEY:
862
error:
863
		prebuilt->trx->error_info = NULL;
864
		/* fall through */
865
	default:
866
		if (new_primary) {
867
			row_merge_drop_table(trx, indexed_table);
868
		} else {
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
869
			if (!dict_locked) {
870
				row_mysql_lock_data_dictionary(trx);
871
				dict_locked = TRUE;
872
			}
873
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
874
			row_merge_drop_indexes(trx, indexed_table,
875
					       index, num_created);
876
		}
877
878
convert_error:
879
		error = convert_error_code_to_mysql(error,
880
						    innodb_table->flags,
641.1.4 by Monty Taylor
Merged in InnoDB changes.
881
						    user_session);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
882
	}
883
884
	mem_heap_free(heap);
885
	trx_commit_for_mysql(trx);
886
	if (prebuilt->trx) {
887
		trx_commit_for_mysql(prebuilt->trx);
888
	}
889
890
	if (dict_locked) {
891
		row_mysql_unlock_data_dictionary(trx);
892
	}
893
894
	trx_free_for_mysql(trx);
895
896
	/* There might be work for utility threads.*/
897
	srv_active_wake_master_thread();
898
641.1.4 by Monty Taylor
Merged in InnoDB changes.
899
	return(error);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
900
}
901
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
902
/*******************************************************************//**
903
Prepare to drop some indexes of a table.
904
@return	0 or error number */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
905
UNIV_INTERN
906
int
907
ha_innobase::prepare_drop_index(
908
/*============================*/
1114.1.1 by Monty Taylor
Merged InnoDB Plugin 1.0.4
909
	Table*	i_table,	/*!< in: Table where indexes are dropped */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
910
	uint*	key_num,	/*!< in: Key nums to be dropped */
911
	uint	num_of_keys)	/*!< in: Number of keys to be dropped */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
912
{
913
	trx_t*		trx;
914
	int		err = 0;
915
	uint 		n_key;
916
779.3.10 by Monty Taylor
Turned on -Wshadow.
917
	ut_ad(i_table);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
918
	ut_ad(key_num);
919
	ut_ad(num_of_keys);
920
	if (srv_created_new_raw || srv_force_recovery) {
641.1.4 by Monty Taylor
Merged in InnoDB changes.
921
		return(HA_ERR_WRONG_COMMAND);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
922
	}
923
641.1.4 by Monty Taylor
Merged in InnoDB changes.
924
	update_session();
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
925
926
	trx_search_latch_release_if_reserved(prebuilt->trx);
927
	trx = prebuilt->trx;
928
929
	/* Test and mark all the indexes to be dropped */
930
931
	row_mysql_lock_data_dictionary(trx);
932
933
	/* Check that none of the indexes have previously been flagged
934
	for deletion. */
935
	{
936
		const dict_index_t*	index
937
			= dict_table_get_first_index(prebuilt->table);
938
		do {
939
			ut_a(!index->to_be_dropped);
940
			index = dict_table_get_next_index(index);
941
		} while (index);
942
	}
943
944
	for (n_key = 0; n_key < num_of_keys; n_key++) {
945
		const KEY*	key;
946
		dict_index_t*	index;
947
779.3.10 by Monty Taylor
Turned on -Wshadow.
948
		key = i_table->key_info + key_num[n_key];
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
949
		index = dict_table_get_index_on_name_and_min_id(
950
			prebuilt->table, key->name);
951
952
		if (!index) {
755.2.1 by Mark Atwood
replace sql_print_error etc with errmsg_print
953
			errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB could not find key n:o %u "
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
954
					"with name %s for table %s",
955
					key_num[n_key],
956
					key ? key->name : "NULL",
957
					prebuilt->table->name);
958
959
			err = HA_ERR_KEY_NOT_FOUND;
960
			goto func_exit;
961
		}
962
963
		/* Refuse to drop the clustered index.  It would be
964
		better to automatically generate a clustered index,
1130.3.13 by Monty Taylor
Finished cleaning namespaces in drizzled/statement
965
		but drizzled::alter_table() will call this method only
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
966
		after ha_innobase::add_index(). */
967
968
		if (dict_index_is_clust(index)) {
969
			my_error(ER_REQUIRES_PRIMARY_KEY, MYF(0));
970
			err = -1;
971
			goto func_exit;
972
		}
973
974
		index->to_be_dropped = TRUE;
975
	}
976
977
	/* If FOREIGN_KEY_CHECK = 1 you may not drop an index defined
978
	for a foreign key constraint because InnoDB requires that both
979
	tables contain indexes for the constraint.  Note that CREATE
980
	INDEX id ON table does a CREATE INDEX and DROP INDEX, and we
981
	can ignore here foreign keys because a new index for the
982
	foreign key has already been created.
983
984
	We check for the foreign key constraints after marking the
985
	candidate indexes for deletion, because when we check for an
986
	equivalent foreign index we don't want to select an index that
987
	is later deleted. */
988
989
	if (trx->check_foreigns
641.1.4 by Monty Taylor
Merged in InnoDB changes.
990
	    && session_sql_command(user_session) != SQLCOM_CREATE_INDEX) {
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
991
		dict_index_t*	index;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
992
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
993
		for (index = dict_table_get_first_index(prebuilt->table);
994
		     index;
995
		     index = dict_table_get_next_index(index)) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
996
			dict_foreign_t*	foreign;
997
998
			if (!index->to_be_dropped) {
999
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1000
				continue;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1001
			}
1002
1003
			/* Check if the index is referenced. */
1004
			foreign = dict_table_get_referenced_constraint(
1005
				prebuilt->table, index);
1006
1007
			if (foreign) {
1008
index_needed:
1009
				trx_set_detailed_error(
1010
					trx,
1011
					"Index needed in foreign key "
1012
					"constraint");
1013
1014
				trx->error_info = index;
1015
1016
				err = HA_ERR_DROP_INDEX_FK;
1017
				break;
1018
			} else {
1019
				/* Check if this index references some
1020
				other table */
1021
				foreign = dict_table_get_foreign_constraint(
1022
					prebuilt->table, index);
1023
1024
				if (foreign) {
1025
					ut_a(foreign->foreign_index == index);
1026
1027
					/* Search for an equivalent index that
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1028
					the foreign key constraint could use
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1029
					if this index were to be deleted. */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1030
					if (!dict_foreign_find_equiv_index(
1031
						foreign)) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1032
1033
						goto index_needed;
1034
					}
1035
				}
1036
			}
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1037
		}
641.1.5 by Monty Taylor
Merged in innodb plugin 1.0.2
1038
	} else if (session_sql_command(user_session) == SQLCOM_CREATE_INDEX) {
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1039
		/* This is a drop of a foreign key constraint index that
1040
		was created by MySQL when the constraint was added.  MySQL
1041
		does this when the user creates an index explicitly which
1042
		can be used in place of the automatically generated index. */
1043
1044
		dict_index_t*	index;
1045
1046
		for (index = dict_table_get_first_index(prebuilt->table);
1047
		     index;
1048
		     index = dict_table_get_next_index(index)) {
1049
			dict_foreign_t*	foreign;
1050
1051
			if (!index->to_be_dropped) {
1052
1053
				continue;
1054
			}
1055
1056
			/* Check if this index references some other table */
1057
			foreign = dict_table_get_foreign_constraint(
1058
				prebuilt->table, index);
1059
1060
			if (foreign == NULL) {
1061
1062
				continue;
1063
			}
1064
1065
			ut_a(foreign->foreign_index == index);
1066
1067
			/* Search for an equivalent index that the
1068
			foreign key constraint could use if this index
1069
			were to be deleted. */
1070
1071
			if (!dict_foreign_find_equiv_index(foreign)) {
1072
				trx_set_detailed_error(
1073
					trx,
1074
					"Index needed in foreign key "
1075
					"constraint");
1076
1077
				trx->error_info = foreign->foreign_index;
1078
1079
				err = HA_ERR_DROP_INDEX_FK;
1080
				break;
1081
			}
1082
		}
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1083
	}
1084
1085
func_exit:
1086
	if (err) {
1087
		/* Undo our changes since there was some sort of error. */
1088
		dict_index_t*	index
1089
			= dict_table_get_first_index(prebuilt->table);
1090
1091
		do {
1092
			index->to_be_dropped = FALSE;
1093
			index = dict_table_get_next_index(index);
1094
		} while (index);
1095
	}
1096
1097
	row_mysql_unlock_data_dictionary(trx);
1098
641.1.4 by Monty Taylor
Merged in InnoDB changes.
1099
	return(err);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1100
}
1101
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1102
/*******************************************************************//**
1103
Drop the indexes that were passed to a successful prepare_drop_index().
1104
@return	0 or error number */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1105
UNIV_INTERN
1106
int
1107
ha_innobase::final_drop_index(
1108
/*==========================*/
1114.1.1 by Monty Taylor
Merged InnoDB Plugin 1.0.4
1109
	Table*	)		/*!< in: Table where indexes are dropped */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1110
{
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1111
	dict_index_t*	index;		/*!< Index to be dropped */
1112
	trx_t*		trx;		/*!< Transaction */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1113
	int		err;
1114
1115
	if (srv_created_new_raw || srv_force_recovery) {
641.1.4 by Monty Taylor
Merged in InnoDB changes.
1116
		return(HA_ERR_WRONG_COMMAND);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1117
	}
1118
641.1.4 by Monty Taylor
Merged in InnoDB changes.
1119
	update_session();
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1120
1121
	trx_search_latch_release_if_reserved(prebuilt->trx);
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1122
	trx_start_if_not_started(prebuilt->trx);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1123
1124
	/* Create a background transaction for the operations on
1125
	the data dictionary tables. */
933.1.2 by Monty Taylor
Fixed merge weirdness errors.
1126
	trx = innobase_trx_allocate(user_session);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1127
	trx_start_if_not_started(trx);
1128
1129
	/* Flag this transaction as a dictionary operation, so that
1130
	the data dictionary will be locked in crash recovery. */
1131
	trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
1132
1133
	/* Lock the table exclusively, to ensure that no active
1134
	transaction depends on an index that is being dropped. */
1135
	err = convert_error_code_to_mysql(
1136
		row_merge_lock_table(prebuilt->trx, prebuilt->table, LOCK_X),
641.1.4 by Monty Taylor
Merged in InnoDB changes.
1137
		prebuilt->table->flags, user_session);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1138
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1139
	row_mysql_lock_data_dictionary(trx);
1140
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1141
	if (UNIV_UNLIKELY(err)) {
1142
1143
		/* Unmark the indexes to be dropped. */
1144
		for (index = dict_table_get_first_index(prebuilt->table);
1145
		     index; index = dict_table_get_next_index(index)) {
1146
1147
			index->to_be_dropped = FALSE;
1148
		}
1149
1150
		goto func_exit;
1151
	}
1152
1153
	/* Drop indexes marked to be dropped */
1154
1155
	index = dict_table_get_first_index(prebuilt->table);
1156
1157
	while (index) {
1158
		dict_index_t*	next_index;
1159
1160
		next_index = dict_table_get_next_index(index);
1161
1162
		if (index->to_be_dropped) {
1163
1164
			row_merge_drop_index(index, prebuilt->table, trx);
1165
		}
1166
1167
		index = next_index;
1168
	}
1169
1170
	/* Check that all flagged indexes were dropped. */
1171
	for (index = dict_table_get_first_index(prebuilt->table);
1172
	     index; index = dict_table_get_next_index(index)) {
1173
		ut_a(!index->to_be_dropped);
1174
	}
1175
1176
#ifdef UNIV_DEBUG
1177
	dict_table_check_for_dup_indexes(prebuilt->table);
1178
#endif
1179
1180
func_exit:
1181
	trx_commit_for_mysql(trx);
1182
	trx_commit_for_mysql(prebuilt->trx);
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1183
	row_mysql_unlock_data_dictionary(trx);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1184
1185
	/* Flush the log to reduce probability that the .frm files and
1186
	the InnoDB data dictionary get out-of-sync if the user runs
1187
	with innodb_flush_log_at_trx_commit = 0 */
1188
1189
	log_buffer_flush_to_disk();
1190
1191
	trx_free_for_mysql(trx);
1192
1193
	/* Tell the InnoDB server that there might be work for
1194
	utility threads: */
1195
1196
	srv_active_wake_master_thread();
1197
641.1.4 by Monty Taylor
Merged in InnoDB changes.
1198
	return(err);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1199
}