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.
26
#include "Discover_ms.h"
31
using namespace drizzled;
33
int ms_create_proto_table(const char *engine_name, const char *name, DT_FIELD_INFO *info, DT_KEY_INFO *keys, drizzled::message::Table *table)
35
message::Table::Field *field;
36
message::Table::Field::FieldConstraints *field_constraints;
37
message::Table::Field::StringFieldOptions *string_field_options;
39
table->set_name(name);
40
table->set_type(message::Table::STANDARD);
41
table->mutable_engine()->set_name(engine_name);
43
while (info->field_name) {
44
field= table->add_field();
46
field->set_name(info->field_name);
48
field->set_comment(info->comment);
50
field_constraints= field->mutable_constraints();
51
if (info->field_flags & NOT_NULL_FLAG)
52
field_constraints->set_is_nullable(true);
54
field_constraints->set_is_nullable(false);
56
if (info->field_flags & UNSIGNED_FLAG)
57
field_constraints->set_is_unsigned(true);
59
field_constraints->set_is_unsigned(false);
61
switch (info->field_type) {
62
case DRIZZLE_TYPE_VARCHAR:
63
string_field_options = field->mutable_string_options();
65
field->set_type(message::Table::Field::VARCHAR);
66
string_field_options->set_length(info->field_length);
67
if (info->field_charset) {
68
string_field_options->set_collation(info->field_charset->name);
69
string_field_options->set_collation_id(info->field_charset->number);
73
case DRIZZLE_TYPE_TINY:
74
field->set_type(message::Table::Field::TINYINT);
77
case DRIZZLE_TYPE_LONG:
78
field->set_type(message::Table::Field::INTEGER);
81
case DRIZZLE_TYPE_DOUBLE:
82
field->set_type(message::Table::Field::DOUBLE);
85
case DRIZZLE_TYPE_LONGLONG:
86
field->set_type(message::Table::Field::BIGINT);
89
case DRIZZLE_TYPE_TIMESTAMP:
90
field->set_type(message::Table::Field::TIMESTAMP);
93
case DRIZZLE_TYPE_BLOB:
94
field->set_type(message::Table::Field::BLOB);
95
if (info->field_charset) {
96
string_field_options = field->mutable_string_options();
97
string_field_options->set_collation(info->field_charset->name);
98
string_field_options->set_collation_id(info->field_charset->number);
111
while (keys->key_name) {
112
// To be done later. (maybe)
122
#include "mysql_priv.h"
123
#include "item_create.h"
125
#include "CSConfig.h"
126
#include "CSGlobal.h"
127
#include "CSThread.h"
131
#if MYSQL_VERSION_ID > 60005
132
#define DOT_STR(x) x.str
137
#define LOCK_OPEN_HACK_REQUIRED
139
#ifdef LOCK_OPEN_HACK_REQUIRED
140
///////////////////////////////
142
* Unfortunately I cannot use the standard mysql_create_table_no_lock() because it will lock "LOCK_open"
143
* which has already been locked while the server is performing table discovery. So I have added this hack
144
* in here to create my own version. The following macros will make the changes I need to get it to work.
145
* The actual function code has been copied here without changes.
147
* Its almost enough to make you want to cry. :(
149
//-----------------------------
151
#ifdef pthread_mutex_lock
152
#undef pthread_mutex_lock
155
#ifdef pthread_mutex_unlock
156
#undef pthread_mutex_unlock
159
#define mysql_create_table_no_lock hacked_mysql_create_table_no_lock
160
#define pthread_mutex_lock(l)
161
#define pthread_mutex_unlock(l)
163
#define check_engine(t, n, c) (0)
164
#define set_table_default_charset(t, c, d)
166
void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
167
uint32 *max_length, uint32 *tot_length);
169
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen);
170
uint build_table_filename(char *buff, size_t bufflen, const char *db,
171
const char *table_name, const char *ext, uint flags);
173
//////////////////////////////////////////////////////////
174
////// START OF CUT AND PASTES FROM sql_table.cc ////////
175
//////////////////////////////////////////////////////////
177
// sort_keys() cut and pasted directly from sql_table.cc.
178
static int sort_keys(KEY *a, KEY *b)
180
ulong a_flags= a->flags, b_flags= b->flags;
182
if (a_flags & HA_NOSAME)
184
if (!(b_flags & HA_NOSAME))
186
if ((a_flags ^ b_flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY))
188
/* Sort NOT NULL keys before other keys */
189
return (a_flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1;
191
if (a->name == primary_key_name)
193
if (b->name == primary_key_name)
195
/* Sort keys don't containing partial segments before others */
196
if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
197
return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1;
199
else if (b_flags & HA_NOSAME)
200
return 1; // Prefer b
202
if ((a_flags ^ b_flags) & HA_FULLTEXT)
204
return (a_flags & HA_FULLTEXT) ? 1 : -1;
207
Prefer original key order. usable_key_parts contains here
208
the original key position.
210
return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
211
(a->usable_key_parts > b->usable_key_parts) ? 1 :
215
// check_if_keyname_exists() cut and pasted directly from sql_table.cc.
217
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
219
for (KEY *key=start ; key != end ; key++)
220
if (!my_strcasecmp(system_charset_info,name,key->name))
225
// make_unique_key_name() cut and pasted directly from sql_table.cc.
227
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
229
char buff[MAX_FIELD_NAME],*buff_end;
231
if (!check_if_keyname_exists(field_name,start,end) &&
232
my_strcasecmp(system_charset_info,field_name,primary_key_name))
233
return (char*) field_name; // Use fieldname
234
buff_end=strmake(buff,field_name, sizeof(buff)-4);
237
Only 3 chars + '\0' left, so need to limit to 2 digit
238
This is ok as we can't have more than 100 keys anyway
240
for (uint i=2 ; i< 100; i++)
243
int10_to_str(i, buff_end+1, 10);
244
if (!check_if_keyname_exists(buff,start,end))
245
return sql_strdup(buff);
247
return (char*) "not_specified"; // Should never happen
251
// prepare_blob_field() cut and pasted directly from sql_table.cc.
252
static bool prepare_blob_field(THD *thd, Create_field *sql_field)
254
DBUG_ENTER("prepare_blob_field");
256
if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
257
!(sql_field->flags & BLOB_FLAG))
259
/* Convert long VARCHAR columns to TEXT or BLOB */
260
char warn_buff[MYSQL_ERRMSG_SIZE];
262
if (sql_field->def || (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
263
MODE_STRICT_ALL_TABLES)))
265
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
266
MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
269
sql_field->sql_type= MYSQL_TYPE_BLOB;
270
sql_field->flags|= BLOB_FLAG;
271
snprintf(warn_buff, MYSQL_ERRMSG_SIZE, ER(ER_AUTO_CONVERT), sql_field->field_name,
272
(sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
273
(sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
274
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
278
if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
280
if (sql_field->sql_type == MYSQL_TYPE_BLOB)
282
/* The user has given a length to the blob column */
283
sql_field->sql_type= get_blob_type_from_length(sql_field->length);
284
sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
286
sql_field->length= 0;
291
//////////////////////////////
292
// mysql_prepare_create_table() cut and pasted directly from sql_table.cc.
294
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
295
Alter_info *alter_info,
298
handler *file, KEY **key_info_buffer,
299
uint *key_count, int select_field_count)
301
const char *key_name;
302
Create_field *sql_field,*dup_field;
303
uint field,null_fields,blob_columns,max_key_length;
304
ulong record_offset= 0;
306
KEY_PART_INFO *key_part_info;
307
int timestamps= 0, timestamps_with_niladic= 0;
309
int select_field_pos,auto_increment=0;
310
List_iterator<Create_field> it(alter_info->create_list);
311
List_iterator<Create_field> it2(alter_info->create_list);
312
uint total_uneven_bit_length= 0;
313
DBUG_ENTER("mysql_prepare_create_table");
315
select_field_pos= alter_info->create_list.elements - select_field_count;
316
null_fields=blob_columns=0;
317
create_info->varchar= 0;
318
max_key_length= file->max_key_length();
320
for (field_no=0; (sql_field=it++) ; field_no++)
322
CHARSET_INFO *save_cs;
325
Initialize length from its original value (number of characters),
326
which was set in the parser. This is necessary if we're
327
executing a prepared statement for the second time.
329
sql_field->length= sql_field->char_length;
330
if (!sql_field->charset)
331
sql_field->charset= create_info->default_table_charset;
333
table_charset is set in ALTER TABLE if we want change character set
334
for all varchar/char columns.
335
But the table charset must not affect the BLOB fields, so don't
336
allow to change my_charset_bin to somethig else.
338
if (create_info->table_charset && sql_field->charset != &my_charset_bin)
339
sql_field->charset= create_info->table_charset;
341
save_cs= sql_field->charset;
342
if ((sql_field->flags & BINCMP_FLAG) &&
343
!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
344
MY_CS_BINSORT,MYF(0))))
347
strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
348
STRING_WITH_LEN("_bin"));
349
my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
354
Convert the default value from client character
355
set into the column character set if necessary.
357
if (sql_field->def &&
358
save_cs != sql_field->def->collation.collation &&
359
(sql_field->sql_type == MYSQL_TYPE_VAR_STRING ||
360
sql_field->sql_type == MYSQL_TYPE_STRING ||
361
sql_field->sql_type == MYSQL_TYPE_SET ||
362
sql_field->sql_type == MYSQL_TYPE_ENUM))
365
Starting from 5.1 we work here with a copy of Create_field
366
created by the caller, not with the instance that was
367
originally created during parsing. It's OK to create
368
a temporary item and initialize with it a member of the
369
copy -- this item will be thrown away along with the copy
370
at the end of execution, and thus not introduce a dangling
371
pointer in the parsed tree of a prepared statement or a
372
stored procedure statement.
374
sql_field->def= sql_field->def->safe_charset_converter(save_cs);
376
if (sql_field->def == NULL)
378
/* Could not convert */
379
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
384
if (sql_field->sql_type == MYSQL_TYPE_SET ||
385
sql_field->sql_type == MYSQL_TYPE_ENUM)
388
CHARSET_INFO *cs= sql_field->charset;
389
TYPELIB *interval= sql_field->interval;
392
Create typelib from interval_list, and if necessary
393
convert strings from client character set to the
394
column character set.
399
Create the typelib in runtime memory - we will free the
400
occupied memory at the same time when we free this
401
sql_field -- at the end of execution.
403
interval= sql_field->interval= typelib(thd->mem_root,
404
sql_field->interval_list);
405
List_iterator<String> int_it(sql_field->interval_list);
408
int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
411
DBUG_ASSERT(comma_length > 0);
412
for (uint i= 0; (tmp= int_it++); i++)
415
if (String::needs_conversion(tmp->length(), tmp->charset(),
419
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
420
interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
422
interval->type_lengths[i]= conv.length();
425
// Strip trailing spaces.
426
lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
427
interval->type_lengths[i]);
428
interval->type_lengths[i]= lengthsp;
429
((uchar *)interval->type_names[i])[lengthsp]= '\0';
430
if (sql_field->sql_type == MYSQL_TYPE_SET)
432
if (cs->coll->instr(cs, interval->type_names[i],
433
interval->type_lengths[i],
434
comma_buf, comma_length, NULL, 0))
436
my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr());
441
sql_field->interval_list.empty(); // Don't need interval_list anymore
444
if (sql_field->sql_type == MYSQL_TYPE_SET)
447
if (sql_field->def != NULL)
452
String str, *def= sql_field->def->val_str(&str);
453
if (def == NULL) /* SQL "NULL" maps to NULL */
455
if ((sql_field->flags & NOT_NULL_FLAG) != 0)
457
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
461
/* else, NULL is an allowed value */
462
(void) find_set(interval, NULL, 0,
463
cs, ¬_used, ¬_used2, ¬_found);
467
(void) find_set(interval, def->ptr(), def->length(),
468
cs, ¬_used, ¬_used2, ¬_found);
473
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
477
calculate_interval_lengths(cs, interval, &dummy, &field_length);
478
sql_field->length= field_length + (interval->count - 1);
480
else /* MYSQL_TYPE_ENUM */
483
DBUG_ASSERT(sql_field->sql_type == MYSQL_TYPE_ENUM);
484
if (sql_field->def != NULL)
486
String str, *def= sql_field->def->val_str(&str);
487
if (def == NULL) /* SQL "NULL" maps to NULL */
489
if ((sql_field->flags & NOT_NULL_FLAG) != 0)
491
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
495
/* else, the defaults yield the correct length for NULLs. */
499
def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
500
if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
502
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
507
calculate_interval_lengths(cs, interval, &field_length, &dummy);
508
sql_field->length= field_length;
510
set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
513
if (sql_field->sql_type == MYSQL_TYPE_BIT)
515
sql_field->pack_flag= FIELDFLAG_NUMBER;
516
if (file->ha_table_flags() & HA_CAN_BIT_FIELD)
517
total_uneven_bit_length+= sql_field->length & 7;
519
sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
522
sql_field->create_length_to_internal_length();
523
if (prepare_blob_field(thd, sql_field))
526
if (!(sql_field->flags & NOT_NULL_FLAG))
529
if (check_column_name(sql_field->field_name))
531
my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
535
/* Check if we have used the same field name before */
536
for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
538
if (my_strcasecmp(system_charset_info,
539
sql_field->field_name,
540
dup_field->field_name) == 0)
543
If this was a CREATE ... SELECT statement, accept a field
544
redefinition if we are changing a field in the SELECT part
546
if (field_no < select_field_pos || dup_no >= select_field_pos)
548
my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
553
/* Field redefined */
554
sql_field->def= dup_field->def;
555
sql_field->sql_type= dup_field->sql_type;
556
sql_field->charset= (dup_field->charset ?
558
create_info->default_table_charset);
559
sql_field->length= dup_field->char_length;
560
sql_field->pack_length= dup_field->pack_length;
561
sql_field->key_length= dup_field->key_length;
562
sql_field->decimals= dup_field->decimals;
563
sql_field->create_length_to_internal_length();
564
sql_field->unireg_check= dup_field->unireg_check;
566
We're making one field from two, the result field will have
567
dup_field->flags as flags. If we've incremented null_fields
568
because of sql_field->flags, decrement it back.
570
if (!(sql_field->flags & NOT_NULL_FLAG))
572
sql_field->flags= dup_field->flags;
573
sql_field->interval= dup_field->interval;
574
it2.remove(); // Remove first (create) definition
580
/* Don't pack rows in old tables if the user has requested this */
581
if ((sql_field->flags & BLOB_FLAG) ||
582
sql_field->sql_type == MYSQL_TYPE_VARCHAR &&
583
create_info->row_type != ROW_TYPE_FIXED)
584
(*db_options)|= HA_OPTION_PACK_RECORD;
588
/* record_offset will be increased with 'length-of-null-bits' later */
590
null_fields+= total_uneven_bit_length;
593
while ((sql_field=it++))
595
DBUG_ASSERT(sql_field->charset != 0);
597
if (prepare_create_field(sql_field, &blob_columns,
598
×tamps, ×tamps_with_niladic,
599
file->ha_table_flags()))
601
if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
602
create_info->varchar= TRUE;
603
sql_field->offset= record_offset;
604
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
606
record_offset+= sql_field->pack_length;
608
if (timestamps_with_niladic > 1)
610
my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
611
ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
614
if (auto_increment > 1)
616
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
619
if (auto_increment &&
620
(file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
622
my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
623
ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
627
if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
629
my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
636
List_iterator<Key> key_iterator(alter_info->key_list);
637
List_iterator<Key> key_iterator2(alter_info->key_list);
638
uint key_parts=0, fk_key_count=0;
639
bool primary_key=0,unique_key=0;
641
uint tmp, key_number;
642
/* special marker for keys to be ignored */
643
static char ignore_key[1];
645
/* Calculate number of key segements */
648
while ((key=key_iterator++))
650
DBUG_PRINT("info", ("key name: '%s' type: %d", key->DOT_STR(name) ? key->DOT_STR(name) :
651
"(none)" , key->type));
652
LEX_STRING key_name_str;
653
if (key->type == Key::FOREIGN_KEY)
656
Foreign_key *fk_key= (Foreign_key*) key;
657
if (fk_key->ref_columns.elements &&
658
fk_key->ref_columns.elements != fk_key->columns.elements)
660
my_error(ER_WRONG_FK_DEF, MYF(0),
661
(fk_key->DOT_STR(name) ? fk_key->DOT_STR(name) : "foreign key without name"),
662
ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
668
tmp=file->max_key_parts();
669
if (key->columns.elements > tmp)
671
my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
674
key_name_str.str= (char*) key->DOT_STR(name);
675
key_name_str.length= key->DOT_STR(name) ? strlen(key->DOT_STR(name)) : 0;
676
if (check_string_char_length(&key_name_str, "", NAME_CHAR_LEN,
677
system_charset_info, 1))
679
my_error(ER_TOO_LONG_IDENT, MYF(0), key->DOT_STR(name));
682
key_iterator2.rewind ();
683
if (key->type != Key::FOREIGN_KEY)
685
while ((key2 = key_iterator2++) != key)
688
foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is
689
'generated', and a generated key is a prefix of the other key.
690
Then we do not need the generated shorter key.
692
if ((key2->type != Key::FOREIGN_KEY &&
693
key2->DOT_STR(name) != ignore_key &&
694
!foreign_key_prefix(key, key2)))
696
/* TODO: issue warning message */
697
/* mark that the generated key should be ignored */
698
if (!key2->generated ||
699
(key->generated && key->columns.elements <
700
key2->columns.elements))
701
key->DOT_STR(name)= ignore_key;
704
key2->DOT_STR(name)= ignore_key;
705
key_parts-= key2->columns.elements;
712
if (key->DOT_STR(name) != ignore_key)
713
key_parts+=key->columns.elements;
716
if (key->DOT_STR(name) && !tmp_table && (key->type != Key::PRIMARY) &&
717
!my_strcasecmp(system_charset_info,key->DOT_STR(name),primary_key_name))
719
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->DOT_STR(name));
723
tmp=file->max_keys();
724
if (*key_count > tmp)
726
my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
730
(*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
731
key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
732
if (!*key_info_buffer || ! key_part_info)
733
DBUG_RETURN(TRUE); // Out of memory
735
key_iterator.rewind();
737
for (; (key=key_iterator++) ; key_number++)
740
Key_part_spec *column;
742
if (key->DOT_STR(name) == ignore_key)
744
/* ignore redundant keys */
747
while (key && key->DOT_STR(name) == ignore_key);
757
key_info->flags= HA_FULLTEXT;
758
if ((key_info->parser_name= &key->key_create_info.parser_name)->str)
759
key_info->flags|= HA_USES_PARSER;
761
key_info->parser_name= 0;
765
key_info->flags= HA_SPATIAL;
768
my_error(ER_FEATURE_DISABLED, MYF(0),
769
sym_group_geom.name, sym_group_geom.needed_define);
772
case Key::FOREIGN_KEY:
773
key_number--; // Skip this key
776
key_info->flags = HA_NOSAME;
780
key_info->flags|= HA_GENERATED_KEY;
782
key_info->key_parts=(uint8) key->columns.elements;
783
key_info->key_part=key_part_info;
784
key_info->usable_key_parts= key_number;
785
key_info->algorithm= key->key_create_info.algorithm;
787
if (key->type == Key::FULLTEXT)
789
if (!(file->ha_table_flags() & HA_CAN_FULLTEXT))
791
my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT),
797
Make SPATIAL to be RTREE by default
798
SPATIAL only on BLOB or at least BINARY, this
799
actually should be replaced by special GEOM type
800
in near future when new frm file is ready
801
checking for proper key parts number:
804
/* TODO: Add proper checks if handler supports key_type and algorithm */
805
if (key_info->flags & HA_SPATIAL)
807
if (!(file->ha_table_flags() & HA_CAN_RTREEKEYS))
809
my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS),
813
if (key_info->key_parts != 1)
815
my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
819
else if (key_info->algorithm == HA_KEY_ALG_RTREE)
821
#ifdef HAVE_RTREE_KEYS
822
if ((key_info->key_parts & 1) == 1)
824
my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX");
827
/* TODO: To be deleted */
828
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX");
831
my_error(ER_FEATURE_DISABLED, MYF(0),
832
sym_group_rtree.name, sym_group_rtree.needed_define);
837
/* Take block size from key part or table part */
839
TODO: Add warning if block size changes. We can't do it here, as
840
this may depend on the size of the key
842
key_info->block_size= (key->key_create_info.block_size ?
843
key->key_create_info.block_size :
844
create_info->key_block_size);
846
if (key_info->block_size)
847
key_info->flags|= HA_USES_BLOCK_SIZE;
849
List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
850
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
851
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
854
Key_part_spec *dup_column;
858
while ((sql_field=it++) &&
859
my_strcasecmp(system_charset_info,
860
column->DOT_STR(field_name),
861
sql_field->field_name))
865
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
868
while ((dup_column= cols2++) != column)
870
if (!my_strcasecmp(system_charset_info,
871
column->DOT_STR(field_name), dup_column->DOT_STR(field_name)))
873
my_printf_error(ER_DUP_FIELDNAME,
874
ER(ER_DUP_FIELDNAME),MYF(0),
880
if (key->type == Key::FULLTEXT)
882
if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
883
sql_field->sql_type != MYSQL_TYPE_VARCHAR &&
884
!f_is_blob(sql_field->pack_flag)) ||
885
sql_field->charset == &my_charset_bin ||
886
sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
887
(ft_key_charset && sql_field->charset != ft_key_charset))
889
my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name);
892
ft_key_charset=sql_field->charset;
894
for fulltext keys keyseg length is 1 for blobs (it's ignored in ft
895
code anyway, and 0 (set to column width later) for char's. it has
896
to be correct col width for char's, as char data are not prefixed
897
with length (unlike blobs, where ft code takes data length from a
898
data prefix, ignoring column->length).
900
column->length=test(f_is_blob(sql_field->pack_flag));
904
column->length*= sql_field->charset->mbmaxlen;
906
if (key->type == Key::SPATIAL && column->length)
908
my_error(ER_WRONG_SUB_KEY, MYF(0));
912
if (f_is_blob(sql_field->pack_flag) ||
913
(f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
915
if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
917
my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name);
920
if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
925
my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name);
930
if (key->type == Key::SPATIAL)
935
4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
936
Lately we'll extend this code to support more dimensions
938
column->length= 4*sizeof(double);
942
if (!(sql_field->flags & NOT_NULL_FLAG))
944
if (key->type == Key::PRIMARY)
946
/* Implicitly set primary key fields to NOT NULL for ISO conf. */
947
sql_field->flags|= NOT_NULL_FLAG;
948
sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
953
key_info->flags|= HA_NULL_PART_KEY;
954
if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
956
my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name);
959
if (key->type == Key::SPATIAL)
961
my_message(ER_SPATIAL_CANT_HAVE_NULL,
962
ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
967
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
969
if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
970
auto_increment--; // Field is used
974
key_part_info->fieldnr= field;
975
key_part_info->offset= (uint16) sql_field->offset;
976
key_part_info->key_type=sql_field->pack_flag;
977
length= sql_field->key_length;
981
if (f_is_blob(sql_field->pack_flag))
983
if ((length=column->length) > max_key_length ||
984
length > file->max_key_part_length())
986
length=min(max_key_length, file->max_key_part_length());
987
if (key->type == Key::MULTIPLE)
989
/* not a critical problem */
990
char warn_buff[MYSQL_ERRMSG_SIZE];
991
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
993
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
994
ER_TOO_LONG_KEY, warn_buff);
995
/* Align key length to multibyte char boundary */
996
length-= length % sql_field->charset->mbmaxlen;
1000
my_error(ER_TOO_LONG_KEY,MYF(0),length);
1005
else if (!f_is_geom(sql_field->pack_flag) &&
1006
(column->length > length ||
1007
!Field::type_can_have_key_part (sql_field->sql_type) ||
1008
((f_is_packed(sql_field->pack_flag) ||
1009
((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
1010
(key_info->flags & HA_NOSAME))) &&
1011
column->length != length)))
1013
my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1016
else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
1017
length=column->length;
1019
else if (length == 0)
1021
my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name);
1024
if (length > file->max_key_part_length() && key->type != Key::FULLTEXT)
1026
length= file->max_key_part_length();
1027
if (key->type == Key::MULTIPLE)
1029
/* not a critical problem */
1030
char warn_buff[MYSQL_ERRMSG_SIZE];
1031
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
1033
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1034
ER_TOO_LONG_KEY, warn_buff);
1035
/* Align key length to multibyte char boundary */
1036
length-= length % sql_field->charset->mbmaxlen;
1040
my_error(ER_TOO_LONG_KEY,MYF(0),length);
1044
key_part_info->length=(uint16) length;
1045
/* Use packed keys for long strings on the first column */
1046
if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
1047
(length >= KEY_DEFAULT_PACK_LENGTH &&
1048
(sql_field->sql_type == MYSQL_TYPE_STRING ||
1049
sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
1050
sql_field->pack_flag & FIELDFLAG_BLOB)))
1052
if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB) ||
1053
sql_field->sql_type == MYSQL_TYPE_VARCHAR)
1054
key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1056
key_info->flags|= HA_PACK_KEY;
1058
/* Check if the key segment is partial, set the key flag accordingly */
1059
if (length != sql_field->key_length)
1060
key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
1065
/* Create the key name based on the first column (if not given) */
1068
if (key->type == Key::PRIMARY)
1072
my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
1076
key_name=primary_key_name;
1079
else if (!(key_name = key->DOT_STR(name)))
1080
key_name=make_unique_key_name(sql_field->field_name,
1081
*key_info_buffer, key_info);
1082
if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
1084
my_error(ER_DUP_KEYNAME, MYF(0), key_name);
1087
key_info->name=(char*) key_name;
1090
if (!key_info->name || check_column_name(key_info->name))
1092
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1095
if (!(key_info->flags & HA_NULL_PART_KEY))
1097
key_info->key_length=(uint16) key_length;
1098
if (key_length > max_key_length && key->type != Key::FULLTEXT)
1100
my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1105
if (!unique_key && !primary_key &&
1106
(file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1108
my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1111
if (auto_increment > 0)
1113
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1116
/* Sort keys in optimized order */
1117
my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
1118
(qsort_cmp) sort_keys);
1119
create_info->null_bits= null_fields;
1123
while ((sql_field=it++))
1125
Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1127
if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
1129
sql_field->sql_type == MYSQL_TYPE_TIMESTAMP &&
1130
(sql_field->flags & NOT_NULL_FLAG) &&
1131
(type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1134
An error should be reported if:
1135
- NO_ZERO_DATE SQL mode is active;
1136
- there is no explicit DEFAULT clause (default column value);
1137
- this is a TIMESTAMP column;
1138
- the column is not NULL;
1139
- this is not the DEFAULT CURRENT_TIMESTAMP column.
1141
In other words, an error should be reported if
1142
- NO_ZERO_DATE SQL mode is active;
1143
- the column definition is equivalent to
1144
'column_name TIMESTAMP DEFAULT 0'.
1147
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
1155
//////////////////////////////
1156
// mysql_create_table_no_lock() cut and pasted directly from sql_table.cc. (I did make is static after copying it.)
1158
static bool mysql_create_table_no_lock(THD *thd,
1159
const char *db, const char *table_name,
1160
HA_CREATE_INFO *create_info,
1161
Alter_info *alter_info,
1162
bool internal_tmp_table,
1163
uint select_field_count)
1165
char path[FN_REFLEN];
1168
uint db_options, key_count;
1169
KEY *key_info_buffer;
1172
DBUG_ENTER("mysql_create_table_no_lock");
1173
DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d",
1174
db, table_name, internal_tmp_table));
1177
/* Check for duplicate fields and check type of table to create */
1178
if (!alter_info->create_list.elements)
1180
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1184
if (check_engine(thd, table_name, create_info))
1186
db_options= create_info->table_options;
1187
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1188
db_options|=HA_OPTION_PACK_RECORD;
1189
alias= table_case_name(create_info, table_name);
1191
/* PMC - Done to avoid getting the partition handler by mistake! */
1192
if (!(file= new (thd->mem_root) ha_pbms(pbms_hton, NULL)))
1194
mem_alloc_error(sizeof(handler));
1200
set_table_default_charset(thd, create_info, (char*) db);
1202
if (mysql_prepare_create_table(thd, create_info, alter_info,
1205
&key_info_buffer, &key_count,
1206
select_field_count))
1209
/* Check if table exists */
1210
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1212
path_length= build_tmptable_filename(thd, path, sizeof(path));
1213
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
1218
/* check if the table name contains FN_DEVCHAR when defined */
1219
if (strchr(alias, FN_DEVCHAR))
1221
my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
1225
path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
1226
internal_tmp_table ? FN_IS_TMP : 0);
1229
/* Check if table already exists */
1230
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1231
find_temporary_table(thd, db, table_name))
1233
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1235
create_info->table_existed= 1; // Mark that table existed
1236
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1237
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1242
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
1246
pthread_mutex_lock(&LOCK_open);
1247
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1249
if (!access(path,F_OK))
1251
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1253
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1254
goto unlock_and_end;
1257
We don't assert here, but check the result, because the table could be
1258
in the table definition cache and in the same time the .frm could be
1259
missing from the disk, in case of manual intervention which deletes
1260
the .frm file. The user has to use FLUSH TABLES; to clear the cache.
1261
Then she could create the table. This case is pretty obscure and
1262
therefore we don't introduce a new error message only for it.
1264
if (get_cached_table_share(db, alias))
1266
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1267
goto unlock_and_end;
1272
Check that table with given name does not already
1273
exist in any storage engine. In such a case it should
1274
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1275
unless user specified CREATE TABLE IF EXISTS
1276
The LOCK_open mutex has been locked to make sure no
1277
one else is attempting to discover the table. Since
1278
it's not on disk as a frm file, no one could be using it!
1280
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1282
bool create_if_not_exists =
1283
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
1284
int retcode = ha_table_exists_in_engine(thd, db, table_name);
1285
DBUG_PRINT("info", ("exists_in_engine: %"PRIu32"",retcode));
1288
case HA_ERR_NO_SUCH_TABLE:
1289
/* Normal case, no table exists. we can go and create it */
1291
case HA_ERR_TABLE_EXIST:
1292
DBUG_PRINT("info", ("Table existed in handler"));
1294
if (create_if_not_exists)
1296
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1297
goto unlock_and_end;
1300
DBUG_PRINT("info", ("error: %"PRIu32" from storage engine", retcode));
1301
my_error(retcode, MYF(0),table_name);
1302
goto unlock_and_end;
1306
thd_proc_info(thd, "creating table");
1307
create_info->table_existed= 0; // Mark that table is created
1309
create_info->table_options=db_options;
1311
path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
1312
if (rea_create_table(thd, path, db, table_name,
1313
create_info, alter_info->create_list,
1314
key_count, key_info_buffer, file))
1315
goto unlock_and_end;
1317
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1319
/* Open table and put in temporary table list */
1320
#if MYSQL_VERSION_ID > 60005
1321
if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
1323
if (!(open_temporary_table(thd, path, db, table_name, 1)))
1326
#if MYSQL_VERSION_ID > 60005
1327
(void) rm_temporary_table(create_info->db_type, path, false);
1329
(void) rm_temporary_table(create_info->db_type, path);
1331
goto unlock_and_end;
1333
thd->thread_specific_used= TRUE;
1337
Don't write statement if:
1338
- It is an internal temporary table,
1339
- Row-based logging is used and it we are creating a temporary table, or
1340
- The binary log is not open.
1341
Otherwise, the statement shall be binlogged.
1343
if (!internal_tmp_table &&
1344
(!thd->current_stmt_binlog_row_based ||
1345
(thd->current_stmt_binlog_row_based &&
1346
!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1347
#if MYSQL_VERSION_ID > 50140
1348
write_bin_log(thd, TRUE, thd->query(), thd->query_length());
1350
write_bin_log(thd, TRUE, thd->query, thd->query_length);
1354
pthread_mutex_unlock(&LOCK_open);
1357
thd_proc_info(thd, "After create");
1363
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1364
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1366
create_info->table_existed= 1; // Mark that table existed
1367
goto unlock_and_end;
1370
////////////////////////////////////////////////////////
1371
////// END OF CUT AND PASTES FROM sql_table.cc ////////
1372
////////////////////////////////////////////////////////
1374
#endif // LOCK_OPEN_HACK_REQUIRED
1377
//------------------------------
1378
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 )
1380
char file_name[FN_REFLEN];
1381
int err = 1, delete_frm = 0;
1382
char field_length_buffer[12], *field_length_ptr;
1383
LEX *save_lex= thd->lex, mylex;
1385
memset(&mylex.create_info, 0, sizeof(HA_CREATE_INFO));
1390
/* setup the create info */
1391
mylex.create_info.db_type = hton;
1392
mylex.create_info.frm_only = 1;
1393
mylex.create_info.default_table_charset = system_charset_info;
1395
/* setup the column info. */
1396
while (info->field_name) {
1397
LEX_STRING field_name, comment;
1398
field_name.str = (char*)(info->field_name);
1399
field_name.length = strlen(info->field_name);
1401
comment.str = (char*)(info->comment);
1402
comment.length = strlen(info->comment);
1404
if (info->field_length) {
1405
snprintf(field_length_buffer, 12, "%d", info->field_length);
1406
field_length_ptr = field_length_buffer;
1408
field_length_ptr = NULL;
1410
if (add_field_to_list(thd, &field_name, info->field_type, field_length_ptr, info->field_decimal_length,
1412
#if MYSQL_VERSION_ID > 60005
1414
COLUMN_FORMAT_TYPE_FIXED,
1416
NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
1417
NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/))
1426
while (keys->key_name) {
1429
enum Key::Keytype type;
1430
List<Key_part_spec> col_list;
1432
while (keys->key_columns[i]) {
1433
lex.str = (char *)(keys->key_columns[i++]);
1434
lex.length = strlen(lex.str);
1435
col_list.push_back(new Key_part_spec(lex, 0));
1436
//col_list.push_back(new Key_part_spec(keys->key_columns[i++], 0));
1439
switch (keys->key_type) {
1441
type = Key::PRIMARY;
1443
case UNIQUE_KEY_FLAG:
1446
case MULTIPLE_KEY_FLAG:
1447
type = Key::MULTIPLE;
1451
key= new Key(type, keys->key_name, strlen(keys->key_name),
1452
&default_key_create_info,
1454
mylex.alter_info.key_list.push_back(key);
1461
/* Create an internal temp table */
1462
if (mysql_create_table_no_lock(thd, db, name, &mylex.create_info, &mylex.alter_info, 1, 0))
1466
/* Read the FRM file. */
1467
build_table_filename(file_name, sizeof(file_name), db, name, "", FN_IS_TMP);
1468
if (readfrm(file_name, frmblob, frmlen))
1475
thd->lex = save_lex;
1478
build_table_filename(file_name, sizeof(file_name), db, name, reg_ext, FN_IS_TMP);
1479
my_delete(file_name, MYF(0));