~drizzle-trunk/drizzle/development

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