1
/* Copyright (c) 2008 PrimeBase Technologies GmbH, Germany
2
* Derived from code Copyright (C) 2000-2004 MySQL AB
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
* Created by Barry Leslie on 8/27/08.
25
#include "discover_ms.h"
27
#include "mysql_priv.h"
28
#include "item_create.h"
30
#include "cslib/CSConfig.h"
31
#include "cslib/CSGlobal.h"
32
#include "cslib/CSThread.h"
36
#if MYSQL_VERSION_ID > 60005
37
#define DOT_STR(x) x.str
42
#define LOCK_OPEN_HACK_REQUIRED
44
#ifdef LOCK_OPEN_HACK_REQUIRED
45
///////////////////////////////
47
* Unfortunately I cannot use the standard mysql_create_table_no_lock() because it will lock "LOCK_open"
48
* which has already been locked while the server is performing table discovery. So I have added this hack
49
* in here to create my own version. The following macros will make the changes I need to get it to work.
50
* The actual function code has been copied here without changes.
52
* Its almost enough to make you want to cry. :(
54
//-----------------------------
56
#ifdef pthread_mutex_lock
57
#undef pthread_mutex_lock
60
#ifdef pthread_mutex_unlock
61
#undef pthread_mutex_unlock
64
#define mysql_create_table_no_lock hacked_mysql_create_table_no_lock
65
#define pthread_mutex_lock(l)
66
#define pthread_mutex_unlock(l)
68
#define check_engine(t, n, c) (0)
69
#define set_table_default_charset(t, c, d)
71
void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
72
uint32 *max_length, uint32 *tot_length);
74
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen);
75
uint build_table_filename(char *buff, size_t bufflen, const char *db,
76
const char *table_name, const char *ext, uint flags);
78
//////////////////////////////////////////////////////////
79
////// START OF CUT AND PASTES FROM sql_table.cc ////////
80
//////////////////////////////////////////////////////////
82
// sort_keys() cut and pasted directly from sql_table.cc.
83
static int sort_keys(KEY *a, KEY *b)
85
ulong a_flags= a->flags, b_flags= b->flags;
87
if (a_flags & HA_NOSAME)
89
if (!(b_flags & HA_NOSAME))
91
if ((a_flags ^ b_flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY))
93
/* Sort NOT NULL keys before other keys */
94
return (a_flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1;
96
if (a->name == primary_key_name)
98
if (b->name == primary_key_name)
100
/* Sort keys don't containing partial segments before others */
101
if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
102
return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1;
104
else if (b_flags & HA_NOSAME)
105
return 1; // Prefer b
107
if ((a_flags ^ b_flags) & HA_FULLTEXT)
109
return (a_flags & HA_FULLTEXT) ? 1 : -1;
112
Prefer original key order. usable_key_parts contains here
113
the original key position.
115
return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
116
(a->usable_key_parts > b->usable_key_parts) ? 1 :
120
// check_if_keyname_exists() cut and pasted directly from sql_table.cc.
122
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
124
for (KEY *key=start ; key != end ; key++)
125
if (!my_strcasecmp(system_charset_info,name,key->name))
130
// make_unique_key_name() cut and pasted directly from sql_table.cc.
132
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
134
char buff[MAX_FIELD_NAME],*buff_end;
136
if (!check_if_keyname_exists(field_name,start,end) &&
137
my_strcasecmp(system_charset_info,field_name,primary_key_name))
138
return (char*) field_name; // Use fieldname
139
buff_end=strmake(buff,field_name, sizeof(buff)-4);
142
Only 3 chars + '\0' left, so need to limit to 2 digit
143
This is ok as we can't have more than 100 keys anyway
145
for (uint i=2 ; i< 100; i++)
148
int10_to_str(i, buff_end+1, 10);
149
if (!check_if_keyname_exists(buff,start,end))
150
return sql_strdup(buff);
152
return (char*) "not_specified"; // Should never happen
156
// prepare_blob_field() cut and pasted directly from sql_table.cc.
157
static bool prepare_blob_field(THD *thd, Create_field *sql_field)
159
DBUG_ENTER("prepare_blob_field");
161
if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
162
!(sql_field->flags & BLOB_FLAG))
164
/* Convert long VARCHAR columns to TEXT or BLOB */
165
char warn_buff[MYSQL_ERRMSG_SIZE];
167
if (sql_field->def || (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
168
MODE_STRICT_ALL_TABLES)))
170
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
171
MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
174
sql_field->sql_type= MYSQL_TYPE_BLOB;
175
sql_field->flags|= BLOB_FLAG;
176
snprintf(warn_buff, MYSQL_ERRMSG_SIZE, ER(ER_AUTO_CONVERT), sql_field->field_name,
177
(sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
178
(sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
179
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
183
if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
185
if (sql_field->sql_type == MYSQL_TYPE_BLOB)
187
/* The user has given a length to the blob column */
188
sql_field->sql_type= get_blob_type_from_length(sql_field->length);
189
sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
191
sql_field->length= 0;
196
//////////////////////////////
197
// mysql_prepare_create_table() cut and pasted directly from sql_table.cc.
199
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
200
Alter_info *alter_info,
203
handler *file, KEY **key_info_buffer,
204
uint *key_count, int select_field_count)
206
const char *key_name;
207
Create_field *sql_field,*dup_field;
208
uint field,null_fields,blob_columns,max_key_length;
209
ulong record_offset= 0;
211
KEY_PART_INFO *key_part_info;
212
int timestamps= 0, timestamps_with_niladic= 0;
214
int select_field_pos,auto_increment=0;
215
List_iterator<Create_field> it(alter_info->create_list);
216
List_iterator<Create_field> it2(alter_info->create_list);
217
uint total_uneven_bit_length= 0;
218
DBUG_ENTER("mysql_prepare_create_table");
220
select_field_pos= alter_info->create_list.elements - select_field_count;
221
null_fields=blob_columns=0;
222
create_info->varchar= 0;
223
max_key_length= file->max_key_length();
225
for (field_no=0; (sql_field=it++) ; field_no++)
227
CHARSET_INFO *save_cs;
230
Initialize length from its original value (number of characters),
231
which was set in the parser. This is necessary if we're
232
executing a prepared statement for the second time.
234
sql_field->length= sql_field->char_length;
235
if (!sql_field->charset)
236
sql_field->charset= create_info->default_table_charset;
238
table_charset is set in ALTER TABLE if we want change character set
239
for all varchar/char columns.
240
But the table charset must not affect the BLOB fields, so don't
241
allow to change my_charset_bin to somethig else.
243
if (create_info->table_charset && sql_field->charset != &my_charset_bin)
244
sql_field->charset= create_info->table_charset;
246
save_cs= sql_field->charset;
247
if ((sql_field->flags & BINCMP_FLAG) &&
248
!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
249
MY_CS_BINSORT,MYF(0))))
252
strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
253
STRING_WITH_LEN("_bin"));
254
my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
259
Convert the default value from client character
260
set into the column character set if necessary.
262
if (sql_field->def &&
263
save_cs != sql_field->def->collation.collation &&
264
(sql_field->sql_type == MYSQL_TYPE_VAR_STRING ||
265
sql_field->sql_type == MYSQL_TYPE_STRING ||
266
sql_field->sql_type == MYSQL_TYPE_SET ||
267
sql_field->sql_type == MYSQL_TYPE_ENUM))
270
Starting from 5.1 we work here with a copy of Create_field
271
created by the caller, not with the instance that was
272
originally created during parsing. It's OK to create
273
a temporary item and initialize with it a member of the
274
copy -- this item will be thrown away along with the copy
275
at the end of execution, and thus not introduce a dangling
276
pointer in the parsed tree of a prepared statement or a
277
stored procedure statement.
279
sql_field->def= sql_field->def->safe_charset_converter(save_cs);
281
if (sql_field->def == NULL)
283
/* Could not convert */
284
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
289
if (sql_field->sql_type == MYSQL_TYPE_SET ||
290
sql_field->sql_type == MYSQL_TYPE_ENUM)
293
CHARSET_INFO *cs= sql_field->charset;
294
TYPELIB *interval= sql_field->interval;
297
Create typelib from interval_list, and if necessary
298
convert strings from client character set to the
299
column character set.
304
Create the typelib in runtime memory - we will free the
305
occupied memory at the same time when we free this
306
sql_field -- at the end of execution.
308
interval= sql_field->interval= typelib(thd->mem_root,
309
sql_field->interval_list);
310
List_iterator<String> int_it(sql_field->interval_list);
313
int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
316
DBUG_ASSERT(comma_length > 0);
317
for (uint i= 0; (tmp= int_it++); i++)
320
if (String::needs_conversion(tmp->length(), tmp->charset(),
324
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
325
interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
327
interval->type_lengths[i]= conv.length();
330
// Strip trailing spaces.
331
lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
332
interval->type_lengths[i]);
333
interval->type_lengths[i]= lengthsp;
334
((uchar *)interval->type_names[i])[lengthsp]= '\0';
335
if (sql_field->sql_type == MYSQL_TYPE_SET)
337
if (cs->coll->instr(cs, interval->type_names[i],
338
interval->type_lengths[i],
339
comma_buf, comma_length, NULL, 0))
341
my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr());
346
sql_field->interval_list.empty(); // Don't need interval_list anymore
349
if (sql_field->sql_type == MYSQL_TYPE_SET)
352
if (sql_field->def != NULL)
357
String str, *def= sql_field->def->val_str(&str);
358
if (def == NULL) /* SQL "NULL" maps to NULL */
360
if ((sql_field->flags & NOT_NULL_FLAG) != 0)
362
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
366
/* else, NULL is an allowed value */
367
(void) find_set(interval, NULL, 0,
368
cs, ¬_used, ¬_used2, ¬_found);
372
(void) find_set(interval, def->ptr(), def->length(),
373
cs, ¬_used, ¬_used2, ¬_found);
378
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
382
calculate_interval_lengths(cs, interval, &dummy, &field_length);
383
sql_field->length= field_length + (interval->count - 1);
385
else /* MYSQL_TYPE_ENUM */
388
DBUG_ASSERT(sql_field->sql_type == MYSQL_TYPE_ENUM);
389
if (sql_field->def != NULL)
391
String str, *def= sql_field->def->val_str(&str);
392
if (def == NULL) /* SQL "NULL" maps to NULL */
394
if ((sql_field->flags & NOT_NULL_FLAG) != 0)
396
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
400
/* else, the defaults yield the correct length for NULLs. */
404
def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
405
if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
407
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
412
calculate_interval_lengths(cs, interval, &field_length, &dummy);
413
sql_field->length= field_length;
415
set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
418
if (sql_field->sql_type == MYSQL_TYPE_BIT)
420
sql_field->pack_flag= FIELDFLAG_NUMBER;
421
if (file->ha_table_flags() & HA_CAN_BIT_FIELD)
422
total_uneven_bit_length+= sql_field->length & 7;
424
sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
427
sql_field->create_length_to_internal_length();
428
if (prepare_blob_field(thd, sql_field))
431
if (!(sql_field->flags & NOT_NULL_FLAG))
434
if (check_column_name(sql_field->field_name))
436
my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
440
/* Check if we have used the same field name before */
441
for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
443
if (my_strcasecmp(system_charset_info,
444
sql_field->field_name,
445
dup_field->field_name) == 0)
448
If this was a CREATE ... SELECT statement, accept a field
449
redefinition if we are changing a field in the SELECT part
451
if (field_no < select_field_pos || dup_no >= select_field_pos)
453
my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
458
/* Field redefined */
459
sql_field->def= dup_field->def;
460
sql_field->sql_type= dup_field->sql_type;
461
sql_field->charset= (dup_field->charset ?
463
create_info->default_table_charset);
464
sql_field->length= dup_field->char_length;
465
sql_field->pack_length= dup_field->pack_length;
466
sql_field->key_length= dup_field->key_length;
467
sql_field->decimals= dup_field->decimals;
468
sql_field->create_length_to_internal_length();
469
sql_field->unireg_check= dup_field->unireg_check;
471
We're making one field from two, the result field will have
472
dup_field->flags as flags. If we've incremented null_fields
473
because of sql_field->flags, decrement it back.
475
if (!(sql_field->flags & NOT_NULL_FLAG))
477
sql_field->flags= dup_field->flags;
478
sql_field->interval= dup_field->interval;
479
it2.remove(); // Remove first (create) definition
485
/* Don't pack rows in old tables if the user has requested this */
486
if ((sql_field->flags & BLOB_FLAG) ||
487
sql_field->sql_type == MYSQL_TYPE_VARCHAR &&
488
create_info->row_type != ROW_TYPE_FIXED)
489
(*db_options)|= HA_OPTION_PACK_RECORD;
493
/* record_offset will be increased with 'length-of-null-bits' later */
495
null_fields+= total_uneven_bit_length;
498
while ((sql_field=it++))
500
DBUG_ASSERT(sql_field->charset != 0);
502
if (prepare_create_field(sql_field, &blob_columns,
503
×tamps, ×tamps_with_niladic,
504
file->ha_table_flags()))
506
if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
507
create_info->varchar= TRUE;
508
sql_field->offset= record_offset;
509
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
511
record_offset+= sql_field->pack_length;
513
if (timestamps_with_niladic > 1)
515
my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
516
ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
519
if (auto_increment > 1)
521
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
524
if (auto_increment &&
525
(file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
527
my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
528
ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
532
if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
534
my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
541
List_iterator<Key> key_iterator(alter_info->key_list);
542
List_iterator<Key> key_iterator2(alter_info->key_list);
543
uint key_parts=0, fk_key_count=0;
544
bool primary_key=0,unique_key=0;
546
uint tmp, key_number;
547
/* special marker for keys to be ignored */
548
static char ignore_key[1];
550
/* Calculate number of key segements */
553
while ((key=key_iterator++))
555
DBUG_PRINT("info", ("key name: '%s' type: %d", key->DOT_STR(name) ? key->DOT_STR(name) :
556
"(none)" , key->type));
557
LEX_STRING key_name_str;
558
if (key->type == Key::FOREIGN_KEY)
561
Foreign_key *fk_key= (Foreign_key*) key;
562
if (fk_key->ref_columns.elements &&
563
fk_key->ref_columns.elements != fk_key->columns.elements)
565
my_error(ER_WRONG_FK_DEF, MYF(0),
566
(fk_key->DOT_STR(name) ? fk_key->DOT_STR(name) : "foreign key without name"),
567
ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
573
tmp=file->max_key_parts();
574
if (key->columns.elements > tmp)
576
my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
579
key_name_str.str= (char*) key->DOT_STR(name);
580
key_name_str.length= key->DOT_STR(name) ? strlen(key->DOT_STR(name)) : 0;
581
if (check_string_char_length(&key_name_str, "", NAME_CHAR_LEN,
582
system_charset_info, 1))
584
my_error(ER_TOO_LONG_IDENT, MYF(0), key->DOT_STR(name));
587
key_iterator2.rewind ();
588
if (key->type != Key::FOREIGN_KEY)
590
while ((key2 = key_iterator2++) != key)
593
foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is
594
'generated', and a generated key is a prefix of the other key.
595
Then we do not need the generated shorter key.
597
if ((key2->type != Key::FOREIGN_KEY &&
598
key2->DOT_STR(name) != ignore_key &&
599
!foreign_key_prefix(key, key2)))
601
/* TODO: issue warning message */
602
/* mark that the generated key should be ignored */
603
if (!key2->generated ||
604
(key->generated && key->columns.elements <
605
key2->columns.elements))
606
key->DOT_STR(name)= ignore_key;
609
key2->DOT_STR(name)= ignore_key;
610
key_parts-= key2->columns.elements;
617
if (key->DOT_STR(name) != ignore_key)
618
key_parts+=key->columns.elements;
621
if (key->DOT_STR(name) && !tmp_table && (key->type != Key::PRIMARY) &&
622
!my_strcasecmp(system_charset_info,key->DOT_STR(name),primary_key_name))
624
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->DOT_STR(name));
628
tmp=file->max_keys();
629
if (*key_count > tmp)
631
my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
635
(*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
636
key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
637
if (!*key_info_buffer || ! key_part_info)
638
DBUG_RETURN(TRUE); // Out of memory
640
key_iterator.rewind();
642
for (; (key=key_iterator++) ; key_number++)
645
Key_part_spec *column;
647
if (key->DOT_STR(name) == ignore_key)
649
/* ignore redundant keys */
652
while (key && key->DOT_STR(name) == ignore_key);
662
key_info->flags= HA_FULLTEXT;
663
if ((key_info->parser_name= &key->key_create_info.parser_name)->str)
664
key_info->flags|= HA_USES_PARSER;
666
key_info->parser_name= 0;
670
key_info->flags= HA_SPATIAL;
673
my_error(ER_FEATURE_DISABLED, MYF(0),
674
sym_group_geom.name, sym_group_geom.needed_define);
677
case Key::FOREIGN_KEY:
678
key_number--; // Skip this key
681
key_info->flags = HA_NOSAME;
685
key_info->flags|= HA_GENERATED_KEY;
687
key_info->key_parts=(uint8) key->columns.elements;
688
key_info->key_part=key_part_info;
689
key_info->usable_key_parts= key_number;
690
key_info->algorithm= key->key_create_info.algorithm;
692
if (key->type == Key::FULLTEXT)
694
if (!(file->ha_table_flags() & HA_CAN_FULLTEXT))
696
my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT),
702
Make SPATIAL to be RTREE by default
703
SPATIAL only on BLOB or at least BINARY, this
704
actually should be replaced by special GEOM type
705
in near future when new frm file is ready
706
checking for proper key parts number:
709
/* TODO: Add proper checks if handler supports key_type and algorithm */
710
if (key_info->flags & HA_SPATIAL)
712
if (!(file->ha_table_flags() & HA_CAN_RTREEKEYS))
714
my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS),
718
if (key_info->key_parts != 1)
720
my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
724
else if (key_info->algorithm == HA_KEY_ALG_RTREE)
726
#ifdef HAVE_RTREE_KEYS
727
if ((key_info->key_parts & 1) == 1)
729
my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX");
732
/* TODO: To be deleted */
733
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX");
736
my_error(ER_FEATURE_DISABLED, MYF(0),
737
sym_group_rtree.name, sym_group_rtree.needed_define);
742
/* Take block size from key part or table part */
744
TODO: Add warning if block size changes. We can't do it here, as
745
this may depend on the size of the key
747
key_info->block_size= (key->key_create_info.block_size ?
748
key->key_create_info.block_size :
749
create_info->key_block_size);
751
if (key_info->block_size)
752
key_info->flags|= HA_USES_BLOCK_SIZE;
754
List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
755
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
756
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
759
Key_part_spec *dup_column;
763
while ((sql_field=it++) &&
764
my_strcasecmp(system_charset_info,
765
column->DOT_STR(field_name),
766
sql_field->field_name))
770
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
773
while ((dup_column= cols2++) != column)
775
if (!my_strcasecmp(system_charset_info,
776
column->DOT_STR(field_name), dup_column->DOT_STR(field_name)))
778
my_printf_error(ER_DUP_FIELDNAME,
779
ER(ER_DUP_FIELDNAME),MYF(0),
785
if (key->type == Key::FULLTEXT)
787
if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
788
sql_field->sql_type != MYSQL_TYPE_VARCHAR &&
789
!f_is_blob(sql_field->pack_flag)) ||
790
sql_field->charset == &my_charset_bin ||
791
sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
792
(ft_key_charset && sql_field->charset != ft_key_charset))
794
my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name);
797
ft_key_charset=sql_field->charset;
799
for fulltext keys keyseg length is 1 for blobs (it's ignored in ft
800
code anyway, and 0 (set to column width later) for char's. it has
801
to be correct col width for char's, as char data are not prefixed
802
with length (unlike blobs, where ft code takes data length from a
803
data prefix, ignoring column->length).
805
column->length=test(f_is_blob(sql_field->pack_flag));
809
column->length*= sql_field->charset->mbmaxlen;
811
if (key->type == Key::SPATIAL && column->length)
813
my_error(ER_WRONG_SUB_KEY, MYF(0));
817
if (f_is_blob(sql_field->pack_flag) ||
818
(f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
820
if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
822
my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name);
825
if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
830
my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name);
835
if (key->type == Key::SPATIAL)
840
4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
841
Lately we'll extend this code to support more dimensions
843
column->length= 4*sizeof(double);
847
if (!(sql_field->flags & NOT_NULL_FLAG))
849
if (key->type == Key::PRIMARY)
851
/* Implicitly set primary key fields to NOT NULL for ISO conf. */
852
sql_field->flags|= NOT_NULL_FLAG;
853
sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
858
key_info->flags|= HA_NULL_PART_KEY;
859
if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
861
my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name);
864
if (key->type == Key::SPATIAL)
866
my_message(ER_SPATIAL_CANT_HAVE_NULL,
867
ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
872
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
874
if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
875
auto_increment--; // Field is used
879
key_part_info->fieldnr= field;
880
key_part_info->offset= (uint16) sql_field->offset;
881
key_part_info->key_type=sql_field->pack_flag;
882
length= sql_field->key_length;
886
if (f_is_blob(sql_field->pack_flag))
888
if ((length=column->length) > max_key_length ||
889
length > file->max_key_part_length())
891
length=min(max_key_length, file->max_key_part_length());
892
if (key->type == Key::MULTIPLE)
894
/* not a critical problem */
895
char warn_buff[MYSQL_ERRMSG_SIZE];
896
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
898
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
899
ER_TOO_LONG_KEY, warn_buff);
900
/* Align key length to multibyte char boundary */
901
length-= length % sql_field->charset->mbmaxlen;
905
my_error(ER_TOO_LONG_KEY,MYF(0),length);
910
else if (!f_is_geom(sql_field->pack_flag) &&
911
(column->length > length ||
912
!Field::type_can_have_key_part (sql_field->sql_type) ||
913
((f_is_packed(sql_field->pack_flag) ||
914
((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
915
(key_info->flags & HA_NOSAME))) &&
916
column->length != length)))
918
my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
921
else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
922
length=column->length;
924
else if (length == 0)
926
my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name);
929
if (length > file->max_key_part_length() && key->type != Key::FULLTEXT)
931
length= file->max_key_part_length();
932
if (key->type == Key::MULTIPLE)
934
/* not a critical problem */
935
char warn_buff[MYSQL_ERRMSG_SIZE];
936
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
938
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
939
ER_TOO_LONG_KEY, warn_buff);
940
/* Align key length to multibyte char boundary */
941
length-= length % sql_field->charset->mbmaxlen;
945
my_error(ER_TOO_LONG_KEY,MYF(0),length);
949
key_part_info->length=(uint16) length;
950
/* Use packed keys for long strings on the first column */
951
if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
952
(length >= KEY_DEFAULT_PACK_LENGTH &&
953
(sql_field->sql_type == MYSQL_TYPE_STRING ||
954
sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
955
sql_field->pack_flag & FIELDFLAG_BLOB)))
957
if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB) ||
958
sql_field->sql_type == MYSQL_TYPE_VARCHAR)
959
key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
961
key_info->flags|= HA_PACK_KEY;
963
/* Check if the key segment is partial, set the key flag accordingly */
964
if (length != sql_field->key_length)
965
key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
970
/* Create the key name based on the first column (if not given) */
973
if (key->type == Key::PRIMARY)
977
my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
981
key_name=primary_key_name;
984
else if (!(key_name = key->DOT_STR(name)))
985
key_name=make_unique_key_name(sql_field->field_name,
986
*key_info_buffer, key_info);
987
if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
989
my_error(ER_DUP_KEYNAME, MYF(0), key_name);
992
key_info->name=(char*) key_name;
995
if (!key_info->name || check_column_name(key_info->name))
997
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1000
if (!(key_info->flags & HA_NULL_PART_KEY))
1002
key_info->key_length=(uint16) key_length;
1003
if (key_length > max_key_length && key->type != Key::FULLTEXT)
1005
my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1010
if (!unique_key && !primary_key &&
1011
(file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1013
my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1016
if (auto_increment > 0)
1018
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1021
/* Sort keys in optimized order */
1022
my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
1023
(qsort_cmp) sort_keys);
1024
create_info->null_bits= null_fields;
1028
while ((sql_field=it++))
1030
Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1032
if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
1034
sql_field->sql_type == MYSQL_TYPE_TIMESTAMP &&
1035
(sql_field->flags & NOT_NULL_FLAG) &&
1036
(type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1039
An error should be reported if:
1040
- NO_ZERO_DATE SQL mode is active;
1041
- there is no explicit DEFAULT clause (default column value);
1042
- this is a TIMESTAMP column;
1043
- the column is not NULL;
1044
- this is not the DEFAULT CURRENT_TIMESTAMP column.
1046
In other words, an error should be reported if
1047
- NO_ZERO_DATE SQL mode is active;
1048
- the column definition is equivalent to
1049
'column_name TIMESTAMP DEFAULT 0'.
1052
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
1060
//////////////////////////////
1061
// mysql_create_table_no_lock() cut and pasted directly from sql_table.cc. (I did make is static after copying it.)
1063
static bool mysql_create_table_no_lock(THD *thd,
1064
const char *db, const char *table_name,
1065
HA_CREATE_INFO *create_info,
1066
Alter_info *alter_info,
1067
bool internal_tmp_table,
1068
uint select_field_count)
1070
char path[FN_REFLEN];
1073
uint db_options, key_count;
1074
KEY *key_info_buffer;
1077
DBUG_ENTER("mysql_create_table_no_lock");
1078
DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d",
1079
db, table_name, internal_tmp_table));
1082
/* Check for duplicate fields and check type of table to create */
1083
if (!alter_info->create_list.elements)
1085
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1089
if (check_engine(thd, table_name, create_info))
1091
db_options= create_info->table_options;
1092
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1093
db_options|=HA_OPTION_PACK_RECORD;
1094
alias= table_case_name(create_info, table_name);
1096
/* PMC - Done to avoid getting the partition handler by mistake! */
1097
if (!(file= new (thd->mem_root) ha_pbms(pbms_hton, NULL)))
1099
mem_alloc_error(sizeof(handler));
1105
set_table_default_charset(thd, create_info, (char*) db);
1107
if (mysql_prepare_create_table(thd, create_info, alter_info,
1110
&key_info_buffer, &key_count,
1111
select_field_count))
1114
/* Check if table exists */
1115
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1117
path_length= build_tmptable_filename(thd, path, sizeof(path));
1118
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
1123
/* check if the table name contains FN_DEVCHAR when defined */
1124
if (strchr(alias, FN_DEVCHAR))
1126
my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
1130
path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
1131
internal_tmp_table ? FN_IS_TMP : 0);
1134
/* Check if table already exists */
1135
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1136
find_temporary_table(thd, db, table_name))
1138
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1140
create_info->table_existed= 1; // Mark that table existed
1141
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1142
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1147
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
1151
pthread_mutex_lock(&LOCK_open);
1152
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1154
if (!access(path,F_OK))
1156
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1158
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1159
goto unlock_and_end;
1162
We don't assert here, but check the result, because the table could be
1163
in the table definition cache and in the same time the .frm could be
1164
missing from the disk, in case of manual intervention which deletes
1165
the .frm file. The user has to use FLUSH TABLES; to clear the cache.
1166
Then she could create the table. This case is pretty obscure and
1167
therefore we don't introduce a new error message only for it.
1169
if (get_cached_table_share(db, alias))
1171
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1172
goto unlock_and_end;
1177
Check that table with given name does not already
1178
exist in any storage engine. In such a case it should
1179
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1180
unless user specified CREATE TABLE IF EXISTS
1181
The LOCK_open mutex has been locked to make sure no
1182
one else is attempting to discover the table. Since
1183
it's not on disk as a frm file, no one could be using it!
1185
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1187
bool create_if_not_exists =
1188
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
1189
int retcode = ha_table_exists_in_engine(thd, db, table_name);
1190
DBUG_PRINT("info", ("exists_in_engine: %"PRIu32"",retcode));
1193
case HA_ERR_NO_SUCH_TABLE:
1194
/* Normal case, no table exists. we can go and create it */
1196
case HA_ERR_TABLE_EXIST:
1197
DBUG_PRINT("info", ("Table existed in handler"));
1199
if (create_if_not_exists)
1201
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1202
goto unlock_and_end;
1205
DBUG_PRINT("info", ("error: %"PRIu32" from storage engine", retcode));
1206
my_error(retcode, MYF(0),table_name);
1207
goto unlock_and_end;
1211
thd_proc_info(thd, "creating table");
1212
create_info->table_existed= 0; // Mark that table is created
1214
create_info->table_options=db_options;
1216
path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
1217
if (rea_create_table(thd, path, db, table_name,
1218
create_info, alter_info->create_list,
1219
key_count, key_info_buffer, file))
1220
goto unlock_and_end;
1222
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1224
/* Open table and put in temporary table list */
1225
#if MYSQL_VERSION_ID > 60005
1226
if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
1228
if (!(open_temporary_table(thd, path, db, table_name, 1)))
1231
#if MYSQL_VERSION_ID > 60005
1232
(void) rm_temporary_table(create_info->db_type, path, false);
1234
(void) rm_temporary_table(create_info->db_type, path);
1236
goto unlock_and_end;
1238
thd->thread_specific_used= TRUE;
1242
Don't write statement if:
1243
- It is an internal temporary table,
1244
- Row-based logging is used and it we are creating a temporary table, or
1245
- The binary log is not open.
1246
Otherwise, the statement shall be binlogged.
1248
if (!internal_tmp_table &&
1249
(!thd->current_stmt_binlog_row_based ||
1250
(thd->current_stmt_binlog_row_based &&
1251
!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1252
#if MYSQL_VERSION_ID > 50140
1253
write_bin_log(thd, TRUE, thd->query(), thd->query_length());
1255
write_bin_log(thd, TRUE, thd->query, thd->query_length);
1259
pthread_mutex_unlock(&LOCK_open);
1262
thd_proc_info(thd, "After create");
1268
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1269
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1271
create_info->table_existed= 1; // Mark that table existed
1272
goto unlock_and_end;
1275
////////////////////////////////////////////////////////
1276
////// END OF CUT AND PASTES FROM sql_table.cc ////////
1277
////////////////////////////////////////////////////////
1279
#endif // LOCK_OPEN_HACK_REQUIRED
1282
//------------------------------
1283
int ms_create_table_frm(handlerton *hton, THD* thd, const char *db, const char *name, DT_FIELD_INFO *info, DT_KEY_INFO *keys, uchar **frmblob, size_t *frmlen )
1285
char file_name[FN_REFLEN];
1286
int err = 1, delete_frm = 0;
1287
char field_length_buffer[12], *field_length_ptr;
1288
LEX *save_lex= thd->lex, mylex;
1290
memset(&mylex.create_info, 0, sizeof(HA_CREATE_INFO));
1295
/* setup the create info */
1296
mylex.create_info.db_type = hton;
1297
mylex.create_info.frm_only = 1;
1298
mylex.create_info.default_table_charset = system_charset_info;
1300
/* setup the column info. */
1301
while (info->field_name) {
1302
LEX_STRING field_name, comment;
1303
field_name.str = (char*)(info->field_name);
1304
field_name.length = strlen(info->field_name);
1306
comment.str = (char*)(info->comment);
1307
comment.length = strlen(info->comment);
1309
if (info->field_length) {
1310
snprintf(field_length_buffer, 12, "%d", info->field_length);
1311
field_length_ptr = field_length_buffer;
1313
field_length_ptr = NULL;
1315
if (add_field_to_list(thd, &field_name, info->field_type, field_length_ptr, info->field_decimal_length,
1317
#if MYSQL_VERSION_ID > 60005
1319
COLUMN_FORMAT_TYPE_FIXED,
1321
NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
1322
NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/))
1331
while (keys->key_name) {
1334
enum Key::Keytype type;
1335
List<Key_part_spec> col_list;
1337
while (keys->key_columns[i]) {
1338
lex.str = (char *)(keys->key_columns[i++]);
1339
lex.length = strlen(lex.str);
1340
col_list.push_back(new Key_part_spec(lex, 0));
1341
//col_list.push_back(new Key_part_spec(keys->key_columns[i++], 0));
1344
switch (keys->key_type) {
1346
type = Key::PRIMARY;
1348
case UNIQUE_KEY_FLAG:
1351
case MULTIPLE_KEY_FLAG:
1352
type = Key::MULTIPLE;
1356
key= new Key(type, keys->key_name, strlen(keys->key_name),
1357
&default_key_create_info,
1359
mylex.alter_info.key_list.push_back(key);
1366
/* Create an internal temp table */
1367
if (mysql_create_table_no_lock(thd, db, name, &mylex.create_info, &mylex.alter_info, 1, 0))
1371
/* Read the FRM file. */
1372
build_table_filename(file_name, sizeof(file_name), db, name, "", FN_IS_TMP);
1373
if (readfrm(file_name, frmblob, frmlen))
1380
thd->lex = save_lex;
1383
build_table_filename(file_name, sizeof(file_name), db, name, reg_ext, FN_IS_TMP);
1384
my_delete(file_name, MYF(0));