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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
* Created by Leslie on 8/27/08.
24
#include "xt_config.h"
28
#include "mysql_priv.h"
29
#include "item_create.h"
32
#include "strutil_xt.h"
34
#include "discover_xt.h"
37
#if MYSQL_VERSION_ID >= 50404
38
#define DOT_STR(x) x.str
43
#define LOCK_OPEN_HACK_REQUIRED
45
#ifdef LOCK_OPEN_HACK_REQUIRED
46
///////////////////////////////
48
* Unfortunately I cannot use the standard mysql_create_table_no_lock() because it will lock "LOCK_open"
49
* which has already been locked while the server is performing table discovery. So I have added this hack
50
* in here to create my own version. The following macros will make the changes I need to get it to work.
51
* The actual function code has been copied here without changes.
53
* Its almost enough to make you want to cry. :(
55
//-----------------------------
57
#ifdef pthread_mutex_lock
58
#undef pthread_mutex_lock
61
#ifdef pthread_mutex_unlock
62
#undef pthread_mutex_unlock
65
#define mysql_create_table_no_lock hacked_mysql_create_table_no_lock
66
#define pthread_mutex_lock(l)
67
#define pthread_mutex_unlock(l)
69
#define check_engine(t, n, c) (0)
70
#define set_table_default_charset(t, c, d)
72
void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
73
uint32 *max_length, uint32 *tot_length);
75
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen);
76
uint build_table_filename(char *buff, size_t bufflen, const char *db,
77
const char *table_name, const char *ext, uint flags);
79
//////////////////////////////////////////////////////////
80
////// START OF CUT AND PASTES FROM sql_table.cc ////////
81
//////////////////////////////////////////////////////////
83
// sort_keys() cut and pasted directly from sql_table.cc.
84
static int sort_keys(KEY *a, KEY *b)
86
ulong a_flags= a->flags, b_flags= b->flags;
88
if (a_flags & HA_NOSAME)
90
if (!(b_flags & HA_NOSAME))
92
if ((a_flags ^ b_flags) & HA_NULL_PART_KEY)
94
/* Sort NOT NULL keys before other keys */
95
return (a_flags & HA_NULL_PART_KEY) ? 1 : -1;
97
if (a->name == primary_key_name)
99
if (b->name == primary_key_name)
101
/* Sort keys don't containing partial segments before others */
102
if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
103
return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1;
105
else if (b_flags & HA_NOSAME)
106
return 1; // Prefer b
108
if ((a_flags ^ b_flags) & HA_FULLTEXT)
110
return (a_flags & HA_FULLTEXT) ? 1 : -1;
113
Prefer original key order. usable_key_parts contains here
114
the original key position.
116
return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
117
(a->usable_key_parts > b->usable_key_parts) ? 1 :
121
// check_if_keyname_exists() cut and pasted directly from sql_table.cc.
123
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
125
for (KEY *key=start ; key != end ; key++)
126
if (!my_strcasecmp(system_charset_info,name,key->name))
131
// make_unique_key_name() cut and pasted directly from sql_table.cc.
133
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
135
char buff[MAX_FIELD_NAME],*buff_end;
137
if (!check_if_keyname_exists(field_name,start,end) &&
138
my_strcasecmp(system_charset_info,field_name,primary_key_name))
139
return (char*) field_name; // Use fieldname
140
buff_end=strmake(buff,field_name, sizeof(buff)-4);
143
Only 3 chars + '\0' left, so need to limit to 2 digit
144
This is ok as we can't have more than 100 keys anyway
146
for (uint i=2 ; i< 100; i++)
149
int10_to_str(i, buff_end+1, 10);
150
if (!check_if_keyname_exists(buff,start,end))
151
return sql_strdup(buff);
153
return (char*) "not_specified"; // Should never happen
157
// prepare_blob_field() cut and pasted directly from sql_table.cc.
158
static bool prepare_blob_field(THD *thd, Create_field *sql_field)
160
DBUG_ENTER("prepare_blob_field");
162
if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
163
!(sql_field->flags & BLOB_FLAG))
165
/* Convert long VARCHAR columns to TEXT or BLOB */
166
char warn_buff[MYSQL_ERRMSG_SIZE];
168
if (sql_field->def || (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
169
MODE_STRICT_ALL_TABLES)))
171
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
172
MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
175
sql_field->sql_type= MYSQL_TYPE_BLOB;
176
sql_field->flags|= BLOB_FLAG;
177
sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
178
(sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
179
(sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
180
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
184
if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
186
if (sql_field->sql_type == MYSQL_TYPE_BLOB)
188
/* The user has given a length to the blob column */
189
sql_field->sql_type= get_blob_type_from_length(sql_field->length);
190
sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
192
sql_field->length= 0;
197
//////////////////////////////
198
// mysql_prepare_create_table() cut and pasted directly from sql_table.cc.
200
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
201
Alter_info *alter_info,
204
handler *file, KEY **key_info_buffer,
205
uint *key_count, int select_field_count)
207
const char *key_name;
208
Create_field *sql_field,*dup_field;
209
uint field,null_fields,blob_columns,max_key_length;
210
ulong record_offset= 0;
212
KEY_PART_INFO *key_part_info;
213
int timestamps= 0, timestamps_with_niladic= 0;
215
int select_field_pos,auto_increment=0;
216
List_iterator<Create_field> it(alter_info->create_list);
217
List_iterator<Create_field> it2(alter_info->create_list);
218
uint total_uneven_bit_length= 0;
219
DBUG_ENTER("mysql_prepare_create_table");
221
select_field_pos= alter_info->create_list.elements - select_field_count;
222
null_fields=blob_columns=0;
223
create_info->varchar= 0;
224
max_key_length= file->max_key_length();
226
for (field_no=0; (sql_field=it++) ; field_no++)
228
CHARSET_INFO *save_cs;
231
Initialize length from its original value (number of characters),
232
which was set in the parser. This is necessary if we're
233
executing a prepared statement for the second time.
235
sql_field->length= sql_field->char_length;
236
if (!sql_field->charset)
237
sql_field->charset= create_info->default_table_charset;
239
table_charset is set in ALTER TABLE if we want change character set
240
for all varchar/char columns.
241
But the table charset must not affect the BLOB fields, so don't
242
allow to change my_charset_bin to somethig else.
244
if (create_info->table_charset && sql_field->charset != &my_charset_bin)
245
sql_field->charset= create_info->table_charset;
247
save_cs= sql_field->charset;
248
if ((sql_field->flags & BINCMP_FLAG) &&
249
!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
250
MY_CS_BINSORT,MYF(0))))
253
strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
254
STRING_WITH_LEN("_bin"));
255
my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
260
Convert the default value from client character
261
set into the column character set if necessary.
263
if (sql_field->def &&
264
save_cs != sql_field->def->collation.collation &&
265
(sql_field->sql_type == MYSQL_TYPE_VAR_STRING ||
266
sql_field->sql_type == MYSQL_TYPE_STRING ||
267
sql_field->sql_type == MYSQL_TYPE_SET ||
268
sql_field->sql_type == MYSQL_TYPE_ENUM))
271
Starting from 5.1 we work here with a copy of Create_field
272
created by the caller, not with the instance that was
273
originally created during parsing. It's OK to create
274
a temporary item and initialize with it a member of the
275
copy -- this item will be thrown away along with the copy
276
at the end of execution, and thus not introduce a dangling
277
pointer in the parsed tree of a prepared statement or a
278
stored procedure statement.
280
sql_field->def= sql_field->def->safe_charset_converter(save_cs);
282
if (sql_field->def == NULL)
284
/* Could not convert */
285
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
290
if (sql_field->sql_type == MYSQL_TYPE_SET ||
291
sql_field->sql_type == MYSQL_TYPE_ENUM)
294
CHARSET_INFO *cs= sql_field->charset;
295
TYPELIB *interval= sql_field->interval;
298
Create typelib from interval_list, and if necessary
299
convert strings from client character set to the
300
column character set.
305
Create the typelib in runtime memory - we will free the
306
occupied memory at the same time when we free this
307
sql_field -- at the end of execution.
309
interval= sql_field->interval= typelib(thd->mem_root,
310
sql_field->interval_list);
311
List_iterator<String> int_it(sql_field->interval_list);
314
int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
317
DBUG_ASSERT(comma_length > 0);
318
for (uint i= 0; (tmp= int_it++); i++)
321
if (String::needs_conversion(tmp->length(), tmp->charset(),
325
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
326
interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
328
interval->type_lengths[i]= conv.length();
331
// Strip trailing spaces.
332
lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
333
interval->type_lengths[i]);
334
interval->type_lengths[i]= lengthsp;
335
((uchar *)interval->type_names[i])[lengthsp]= '\0';
336
if (sql_field->sql_type == MYSQL_TYPE_SET)
338
if (cs->coll->instr(cs, interval->type_names[i],
339
interval->type_lengths[i],
340
comma_buf, comma_length, NULL, 0))
342
my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr());
347
sql_field->interval_list.empty(); // Don't need interval_list anymore
350
if (sql_field->sql_type == MYSQL_TYPE_SET)
353
if (sql_field->def != NULL)
358
String str, *def= sql_field->def->val_str(&str);
359
if (def == NULL) /* SQL "NULL" maps to NULL */
361
if ((sql_field->flags & NOT_NULL_FLAG) != 0)
363
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
367
/* else, NULL is an allowed value */
368
(void) find_set(interval, NULL, 0,
369
cs, ¬_used, ¬_used2, ¬_found);
373
(void) find_set(interval, def->ptr(), def->length(),
374
cs, ¬_used, ¬_used2, ¬_found);
379
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
383
calculate_interval_lengths(cs, interval, &dummy, &field_length);
384
sql_field->length= field_length + (interval->count - 1);
386
else /* MYSQL_TYPE_ENUM */
389
DBUG_ASSERT(sql_field->sql_type == MYSQL_TYPE_ENUM);
390
if (sql_field->def != NULL)
392
String str, *def= sql_field->def->val_str(&str);
393
if (def == NULL) /* SQL "NULL" maps to NULL */
395
if ((sql_field->flags & NOT_NULL_FLAG) != 0)
397
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
401
/* else, the defaults yield the correct length for NULLs. */
405
def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
406
if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
408
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
413
calculate_interval_lengths(cs, interval, &field_length, &dummy);
414
sql_field->length= field_length;
416
set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
419
if (sql_field->sql_type == MYSQL_TYPE_BIT)
421
sql_field->pack_flag= FIELDFLAG_NUMBER;
422
if (file->ha_table_flags() & HA_CAN_BIT_FIELD)
423
total_uneven_bit_length+= sql_field->length & 7;
425
sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
428
sql_field->create_length_to_internal_length();
429
if (prepare_blob_field(thd, sql_field))
432
if (!(sql_field->flags & NOT_NULL_FLAG))
435
if (check_column_name(sql_field->field_name))
437
my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
441
/* Check if we have used the same field name before */
442
for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
444
if (my_strcasecmp(system_charset_info,
445
sql_field->field_name,
446
dup_field->field_name) == 0)
449
If this was a CREATE ... SELECT statement, accept a field
450
redefinition if we are changing a field in the SELECT part
452
if (field_no < select_field_pos || dup_no >= select_field_pos)
454
my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
459
/* Field redefined */
460
sql_field->def= dup_field->def;
461
sql_field->sql_type= dup_field->sql_type;
462
sql_field->charset= (dup_field->charset ?
464
create_info->default_table_charset);
465
sql_field->length= dup_field->char_length;
466
sql_field->pack_length= dup_field->pack_length;
467
sql_field->key_length= dup_field->key_length;
468
sql_field->decimals= dup_field->decimals;
469
sql_field->create_length_to_internal_length();
470
sql_field->unireg_check= dup_field->unireg_check;
472
We're making one field from two, the result field will have
473
dup_field->flags as flags. If we've incremented null_fields
474
because of sql_field->flags, decrement it back.
476
if (!(sql_field->flags & NOT_NULL_FLAG))
478
sql_field->flags= dup_field->flags;
479
sql_field->interval= dup_field->interval;
480
it2.remove(); // Remove first (create) definition
486
/* Don't pack rows in old tables if the user has requested this */
487
if ((sql_field->flags & BLOB_FLAG) ||
488
(sql_field->sql_type == MYSQL_TYPE_VARCHAR &&
489
create_info->row_type != ROW_TYPE_FIXED))
490
(*db_options)|= HA_OPTION_PACK_RECORD;
494
/* record_offset will be increased with 'length-of-null-bits' later */
496
null_fields+= total_uneven_bit_length;
499
while ((sql_field=it++))
501
DBUG_ASSERT(sql_field->charset != 0);
503
if (prepare_create_field(sql_field, &blob_columns,
504
×tamps, ×tamps_with_niladic,
505
file->ha_table_flags()))
507
if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
508
create_info->varchar= TRUE;
509
sql_field->offset= record_offset;
510
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
512
record_offset+= sql_field->pack_length;
514
if (timestamps_with_niladic > 1)
516
my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
517
ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
520
if (auto_increment > 1)
522
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
525
if (auto_increment &&
526
(file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
528
my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
529
ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
533
if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
535
my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
542
List_iterator<Key> key_iterator(alter_info->key_list);
543
List_iterator<Key> key_iterator2(alter_info->key_list);
544
uint key_parts=0, fk_key_count=0;
545
bool primary_key=0,unique_key=0;
547
uint tmp, key_number;
548
/* special marker for keys to be ignored */
549
static char ignore_key[1];
551
/* Calculate number of key segements */
554
while ((key=key_iterator++))
556
DBUG_PRINT("info", ("key name: '%s' type: %d", key->DOT_STR(name) ? key->DOT_STR(name) :
557
"(none)" , key->type));
558
LEX_STRING key_name_str;
559
if (key->type == Key::FOREIGN_KEY)
562
Foreign_key *fk_key= (Foreign_key*) key;
563
if (fk_key->ref_columns.elements &&
564
fk_key->ref_columns.elements != fk_key->columns.elements)
566
my_error(ER_WRONG_FK_DEF, MYF(0),
567
(fk_key->DOT_STR(name) ? fk_key->DOT_STR(name) : "foreign key without name"),
568
ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
574
tmp=file->max_key_parts();
575
if (key->columns.elements > tmp)
577
my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
580
key_name_str.str= (char*) key->DOT_STR(name);
581
key_name_str.length= key->DOT_STR(name) ? strlen(key->DOT_STR(name)) : 0;
582
if (check_string_char_length(&key_name_str, "", NAME_CHAR_LEN,
583
system_charset_info, 1))
585
my_error(ER_TOO_LONG_IDENT, MYF(0), key->DOT_STR(name));
588
key_iterator2.rewind ();
589
if (key->type != Key::FOREIGN_KEY)
591
while ((key2 = key_iterator2++) != key)
594
foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is
595
'generated', and a generated key is a prefix of the other key.
596
Then we do not need the generated shorter key.
598
if ((key2->type != Key::FOREIGN_KEY &&
599
key2->DOT_STR(name) != ignore_key &&
600
!foreign_key_prefix(key, key2)))
602
/* TODO: issue warning message */
603
/* mark that the generated key should be ignored */
604
if (!key2->generated ||
605
(key->generated && key->columns.elements <
606
key2->columns.elements))
607
key->DOT_STR(name)= ignore_key;
610
key2->DOT_STR(name)= ignore_key;
611
key_parts-= key2->columns.elements;
618
if (key->DOT_STR(name) != ignore_key)
619
key_parts+=key->columns.elements;
622
if (key->DOT_STR(name) && !tmp_table && (key->type != Key::PRIMARY) &&
623
!my_strcasecmp(system_charset_info,key->DOT_STR(name),primary_key_name))
625
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->DOT_STR(name));
629
tmp=file->max_keys();
630
if (*key_count > tmp)
632
my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
636
(*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
637
key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
638
if (!*key_info_buffer || ! key_part_info)
639
DBUG_RETURN(TRUE); // Out of memory
641
key_iterator.rewind();
643
for (; (key=key_iterator++) ; key_number++)
646
Key_part_spec *column;
648
if (key->DOT_STR(name) == ignore_key)
650
/* ignore redundant keys */
653
while (key && key->DOT_STR(name) == ignore_key);
663
key_info->flags= HA_FULLTEXT;
664
if ((key_info->parser_name= &key->key_create_info.parser_name)->str)
665
key_info->flags|= HA_USES_PARSER;
667
key_info->parser_name= 0;
671
key_info->flags= HA_SPATIAL;
674
my_error(ER_FEATURE_DISABLED, MYF(0),
675
sym_group_geom.name, sym_group_geom.needed_define);
678
case Key::FOREIGN_KEY:
679
key_number--; // Skip this key
682
key_info->flags = HA_NOSAME;
686
key_info->flags|= HA_GENERATED_KEY;
688
key_info->key_parts=(uint8) key->columns.elements;
689
key_info->key_part=key_part_info;
690
key_info->usable_key_parts= key_number;
691
key_info->algorithm= key->key_create_info.algorithm;
693
if (key->type == Key::FULLTEXT)
695
if (!(file->ha_table_flags() & HA_CAN_FULLTEXT))
697
my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT),
703
Make SPATIAL to be RTREE by default
704
SPATIAL only on BLOB or at least BINARY, this
705
actually should be replaced by special GEOM type
706
in near future when new frm file is ready
707
checking for proper key parts number:
710
/* TODO: Add proper checks if handler supports key_type and algorithm */
711
if (key_info->flags & HA_SPATIAL)
713
if (!(file->ha_table_flags() & HA_CAN_RTREEKEYS))
715
my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS),
719
if (key_info->key_parts != 1)
721
my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
725
else if (key_info->algorithm == HA_KEY_ALG_RTREE)
727
#ifdef HAVE_RTREE_KEYS
728
if ((key_info->key_parts & 1) == 1)
730
my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX");
733
/* TODO: To be deleted */
734
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX");
737
my_error(ER_FEATURE_DISABLED, MYF(0),
738
sym_group_rtree.name, sym_group_rtree.needed_define);
743
/* Take block size from key part or table part */
745
TODO: Add warning if block size changes. We can't do it here, as
746
this may depend on the size of the key
748
key_info->block_size= (key->key_create_info.block_size ?
749
key->key_create_info.block_size :
750
create_info->key_block_size);
752
if (key_info->block_size)
753
key_info->flags|= HA_USES_BLOCK_SIZE;
755
List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
756
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
757
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
760
Key_part_spec *dup_column;
764
while ((sql_field=it++) &&
765
my_strcasecmp(system_charset_info,
766
column->DOT_STR(field_name),
767
sql_field->field_name))
771
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
774
while ((dup_column= cols2++) != column)
776
if (!my_strcasecmp(system_charset_info,
777
column->DOT_STR(field_name), dup_column->DOT_STR(field_name)))
779
my_printf_error(ER_DUP_FIELDNAME,
780
ER(ER_DUP_FIELDNAME),MYF(0),
786
if (key->type == Key::FULLTEXT)
788
if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
789
sql_field->sql_type != MYSQL_TYPE_VARCHAR &&
790
!f_is_blob(sql_field->pack_flag)) ||
791
sql_field->charset == &my_charset_bin ||
792
sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
793
(ft_key_charset && sql_field->charset != ft_key_charset))
795
my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name);
798
ft_key_charset=sql_field->charset;
800
for fulltext keys keyseg length is 1 for blobs (it's ignored in ft
801
code anyway, and 0 (set to column width later) for char's. it has
802
to be correct col width for char's, as char data are not prefixed
803
with length (unlike blobs, where ft code takes data length from a
804
data prefix, ignoring column->length).
806
column->length=test(f_is_blob(sql_field->pack_flag));
810
column->length*= sql_field->charset->mbmaxlen;
812
if (key->type == Key::SPATIAL && column->length)
814
my_error(ER_WRONG_SUB_KEY, MYF(0));
818
if (f_is_blob(sql_field->pack_flag) ||
819
(f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
821
if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
823
my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name);
826
if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
831
my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name);
836
if (key->type == Key::SPATIAL)
841
4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
842
Lately we'll extend this code to support more dimensions
844
column->length= 4*sizeof(double);
848
if (!(sql_field->flags & NOT_NULL_FLAG))
850
if (key->type == Key::PRIMARY)
852
/* Implicitly set primary key fields to NOT NULL for ISO conf. */
853
sql_field->flags|= NOT_NULL_FLAG;
854
sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
859
key_info->flags|= HA_NULL_PART_KEY;
860
if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
862
my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name);
865
if (key->type == Key::SPATIAL)
867
my_message(ER_SPATIAL_CANT_HAVE_NULL,
868
ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
873
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
875
if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
876
auto_increment--; // Field is used
880
key_part_info->fieldnr= field;
881
key_part_info->offset= (uint16) sql_field->offset;
882
key_part_info->key_type=sql_field->pack_flag;
883
length= sql_field->key_length;
887
if (f_is_blob(sql_field->pack_flag))
889
if ((length=column->length) > max_key_length ||
890
length > file->max_key_part_length())
892
length=min(max_key_length, file->max_key_part_length());
893
if (key->type == Key::MULTIPLE)
895
/* not a critical problem */
896
char warn_buff[MYSQL_ERRMSG_SIZE];
897
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
899
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
900
ER_TOO_LONG_KEY, warn_buff);
901
/* Align key length to multibyte char boundary */
902
length-= length % sql_field->charset->mbmaxlen;
906
my_error(ER_TOO_LONG_KEY,MYF(0),length);
911
else if (!f_is_geom(sql_field->pack_flag) &&
912
(column->length > length ||
913
!Field::type_can_have_key_part (sql_field->sql_type) ||
914
((f_is_packed(sql_field->pack_flag) ||
915
((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
916
(key_info->flags & HA_NOSAME))) &&
917
column->length != length)))
919
my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
922
else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
923
length=column->length;
925
else if (length == 0)
927
my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name);
930
if (length > file->max_key_part_length() && key->type != Key::FULLTEXT)
932
length= file->max_key_part_length();
933
if (key->type == Key::MULTIPLE)
935
/* not a critical problem */
936
char warn_buff[MYSQL_ERRMSG_SIZE];
937
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
939
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
940
ER_TOO_LONG_KEY, warn_buff);
941
/* Align key length to multibyte char boundary */
942
length-= length % sql_field->charset->mbmaxlen;
946
my_error(ER_TOO_LONG_KEY,MYF(0),length);
950
key_part_info->length=(uint16) length;
951
/* Use packed keys for long strings on the first column */
952
if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
953
(length >= KEY_DEFAULT_PACK_LENGTH &&
954
(sql_field->sql_type == MYSQL_TYPE_STRING ||
955
sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
956
sql_field->pack_flag & FIELDFLAG_BLOB)))
958
if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
959
sql_field->sql_type == MYSQL_TYPE_VARCHAR)
960
key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
962
key_info->flags|= HA_PACK_KEY;
964
/* Check if the key segment is partial, set the key flag accordingly */
965
if (length != sql_field->key_length)
966
key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
971
/* Create the key name based on the first column (if not given) */
974
if (key->type == Key::PRIMARY)
978
my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
982
key_name=primary_key_name;
985
else if (!(key_name = key->DOT_STR(name)))
986
key_name=make_unique_key_name(sql_field->field_name,
987
*key_info_buffer, key_info);
988
if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
990
my_error(ER_DUP_KEYNAME, MYF(0), key_name);
993
key_info->name=(char*) key_name;
996
if (!key_info->name || check_column_name(key_info->name))
998
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1001
if (!(key_info->flags & HA_NULL_PART_KEY))
1003
key_info->key_length=(uint16) key_length;
1004
if (key_length > max_key_length && key->type != Key::FULLTEXT)
1006
my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1011
if (!unique_key && !primary_key &&
1012
(file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1014
my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1017
if (auto_increment > 0)
1019
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1022
/* Sort keys in optimized order */
1023
my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
1024
(qsort_cmp) sort_keys);
1025
create_info->null_bits= null_fields;
1029
while ((sql_field=it++))
1031
Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1033
if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
1035
sql_field->sql_type == MYSQL_TYPE_TIMESTAMP &&
1036
(sql_field->flags & NOT_NULL_FLAG) &&
1037
(type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1040
An error should be reported if:
1041
- NO_ZERO_DATE SQL mode is active;
1042
- there is no explicit DEFAULT clause (default column value);
1043
- this is a TIMESTAMP column;
1044
- the column is not NULL;
1045
- this is not the DEFAULT CURRENT_TIMESTAMP column.
1047
In other words, an error should be reported if
1048
- NO_ZERO_DATE SQL mode is active;
1049
- the column definition is equivalent to
1050
'column_name TIMESTAMP DEFAULT 0'.
1053
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
1061
//////////////////////////////
1062
// mysql_create_table_no_lock() cut and pasted directly from sql_table.cc. (I did make is static after copying it.)
1064
static bool mysql_create_table_no_lock(THD *thd,
1065
const char *db, const char *table_name,
1066
HA_CREATE_INFO *create_info,
1067
Alter_info *alter_info,
1068
bool internal_tmp_table,
1069
uint select_field_count)
1071
char path[FN_REFLEN];
1074
uint db_options, key_count;
1075
KEY *key_info_buffer;
1078
DBUG_ENTER("mysql_create_table_no_lock");
1079
DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d",
1080
db, table_name, internal_tmp_table));
1083
/* Check for duplicate fields and check type of table to create */
1084
if (!alter_info->create_list.elements)
1086
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1090
if (check_engine(thd, table_name, create_info))
1092
db_options= create_info->table_options;
1093
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1094
db_options|=HA_OPTION_PACK_RECORD;
1095
alias= table_case_name(create_info, table_name);
1097
/* PMC - Done to avoid getting the partition handler by mistake! */
1098
if (!(file= new (thd->mem_root) ha_xtsys(pbxt_hton, NULL)))
1100
mem_alloc_error(sizeof(handler));
1104
set_table_default_charset(thd, create_info, (char*) db);
1106
if (mysql_prepare_create_table(thd, create_info, alter_info,
1109
&key_info_buffer, &key_count,
1110
select_field_count))
1113
/* Check if table exists */
1114
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1116
path_length= build_tmptable_filename(thd, path, sizeof(path));
1117
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
1122
/* check if the table name contains FN_DEVCHAR when defined */
1123
if (strchr(alias, FN_DEVCHAR))
1125
my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
1129
path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
1130
internal_tmp_table ? FN_IS_TMP : 0);
1133
/* Check if table already exists */
1134
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1135
find_temporary_table(thd, db, table_name))
1137
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1139
create_info->table_existed= 1; // Mark that table existed
1140
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1141
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1146
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
1150
MYSQL_LOCK(LOCK_open);
1151
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1153
if (!access(path,F_OK))
1155
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1157
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1158
goto unlock_and_end;
1161
We don't assert here, but check the result, because the table could be
1162
in the table definition cache and in the same time the .frm could be
1163
missing from the disk, in case of manual intervention which deletes
1164
the .frm file. The user has to use FLUSH TABLES; to clear the cache.
1165
Then she could create the table. This case is pretty obscure and
1166
therefore we don't introduce a new error message only for it.
1168
if (get_cached_table_share(db, alias))
1170
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1171
goto unlock_and_end;
1176
Check that table with given name does not already
1177
exist in any storage engine. In such a case it should
1178
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1179
unless user specified CREATE TABLE IF EXISTS
1180
The LOCK_open mutex has been locked to make sure no
1181
one else is attempting to discover the table. Since
1182
it's not on disk as a frm file, no one could be using it!
1184
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1186
bool create_if_not_exists =
1187
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
1188
int retcode = ha_table_exists_in_engine(thd, db, table_name);
1189
DBUG_PRINT("info", ("exists_in_engine: %u",retcode));
1192
case HA_ERR_NO_SUCH_TABLE:
1193
/* Normal case, no table exists. we can go and create it */
1195
case HA_ERR_TABLE_EXIST:
1196
DBUG_PRINT("info", ("Table existed in handler"));
1198
if (create_if_not_exists)
1200
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1201
goto unlock_and_end;
1204
DBUG_PRINT("info", ("error: %u from storage engine", retcode));
1205
my_error(retcode, MYF(0),table_name);
1206
goto unlock_and_end;
1210
thd_proc_info(thd, "creating table");
1211
create_info->table_existed= 0; // Mark that table is created
1213
create_info->table_options=db_options;
1215
path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
1216
if (rea_create_table(thd, path, db, table_name,
1217
create_info, alter_info->create_list,
1218
key_count, key_info_buffer, file))
1219
goto unlock_and_end;
1221
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1223
/* Open table and put in temporary table list */
1224
#if MYSQL_VERSION_ID >= 50404
1225
if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
1227
if (!(open_temporary_table(thd, path, db, table_name, 1)))
1230
#if MYSQL_VERSION_ID >= 50404
1231
(void) rm_temporary_table(create_info->db_type, path, false);
1233
(void) rm_temporary_table(create_info->db_type, path);
1235
goto unlock_and_end;
1237
thd->thread_specific_used= TRUE;
1241
Don't write statement if:
1242
- It is an internal temporary table,
1243
- Row-based logging is used and it we are creating a temporary table, or
1244
- The binary log is not open.
1245
Otherwise, the statement shall be binlogged.
1248
* Firstly we had a compile problem with MySQL 5.1.42 and
1249
* the write_bin_log() call below:
1250
* discover_xt.cc:1259: error: argument of type 'char* (Statement::)()' does not match 'const char*'
1252
* And secondly, we should no write the BINLOG anyway because this is
1253
* an internal PBXT system table.
1255
* So I am just commenting out the code altogether.
1256
if (!internal_tmp_table &&
1257
(!thd->current_stmt_binlog_row_based ||
1258
(thd->current_stmt_binlog_row_based &&
1259
!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1260
write_bin_log(thd, TRUE, thd->query, thd->query_length);
1264
MYSQL_UNLOCK(LOCK_open);
1267
thd_proc_info(thd, "After create");
1273
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1274
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1276
create_info->table_existed= 1; // Mark that table existed
1277
goto unlock_and_end;
1280
////////////////////////////////////////////////////////
1281
////// END OF CUT AND PASTES FROM sql_table.cc ////////
1282
////////////////////////////////////////////////////////
1284
#endif // LOCK_OPEN_HACK_REQUIRED
1286
//------------------------------
1287
int xt_create_table_frm(handlerton *hton, THD* thd, const char *db, const char *name, DT_FIELD_INFO *info, DT_KEY_INFO *XT_UNUSED(keys), xtBool skip_existing)
1289
static const char *ext = ".frm";
1290
static const int ext_len = 4;
1292
char field_length_buffer[12], *field_length_ptr;
1293
LEX *save_lex= thd->lex, mylex;
1295
memset(&mylex.create_info, 0, sizeof(HA_CREATE_INFO));
1300
/* setup the create info */
1301
mylex.create_info.db_type = hton;
1303
mylex.create_info.frm_only = 1;
1304
mylex.create_info.default_table_charset = system_charset_info;
1306
/* setup the column info. */
1307
while (info->field_name) {
1308
LEX_STRING field_name, comment;
1309
field_name.str = (char*)(info->field_name);
1310
field_name.length = strlen(info->field_name);
1312
comment.str = (char*)(info->comment);
1313
comment.length = strlen(info->comment);
1315
if (info->field_length) {
1316
sprintf(field_length_buffer, "%d", info->field_length);
1317
field_length_ptr = field_length_buffer;
1319
field_length_ptr = NULL;
1321
if (add_field_to_list(thd, &field_name, info->field_type, field_length_ptr, info->field_decimal_length,
1323
#if MYSQL_VERSION_ID >= 50404
1325
COLUMN_FORMAT_TYPE_FIXED,
1327
NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
1328
NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/
1329
#ifdef MARIADB_BASE_VERSION
1330
, NULL /*vcol_info*/, NULL /* create options */
1339
if (skip_existing) {
1340
size_t db_len = strlen(db);
1341
size_t name_len = strlen(name);
1342
size_t len = db_len + 1 + name_len + ext_len + 1;
1343
char *path = (char *)xt_malloc_ns(len);
1344
memcpy(path, db, db_len);
1345
memcpy(path + db_len + 1, name, name_len);
1346
memcpy(path + db_len + 1 + name_len, ext, ext_len);
1347
path[db_len] = XT_DIR_CHAR;
1348
path[len - 1] = '\0';
1349
xtBool exists = xt_fs_exists(path);
1355
/* Create an internal temp table */
1356
#ifdef WITH_PARTITION_STORAGE_ENGINE
1357
partition_info *part_info;
1359
part_info = thd->work_part_info;
1361
if (mysql_create_table_no_lock(thd, db, name, &mylex.create_info, &mylex.alter_info, 1, 0))
1363
#ifdef WITH_PARTITION_STORAGE_ENGINE
1364
thd->work_part_info = part_info;
1372
thd->lex = save_lex;