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 Leslie on 8/27/08.
24
#include "xt_config.h"
27
#include "mysql_priv.h"
28
#include "item_create.h"
31
#include <drizzled/session.h>
32
#include <drizzled/sql_base.h>
33
#include <drizzled/statement/alter_table.h>
34
#include <drizzled/sql_table.h>
37
extern pid_t drizzled::current_pid;
40
size_t unpack_filename(char * to, const char *from);
43
using namespace drizzled;
44
using namespace drizzled::internal;
47
#include "strutil_xt.h"
49
#include "discover_xt.h"
53
#if MYSQL_VERSION_ID >= 50404
54
#define DOT_STR(x) x.str
61
#define LOCK_OPEN_HACK_REQUIRED
64
#ifdef LOCK_OPEN_HACK_REQUIRED
67
using namespace drizzled;
70
#define mysql_create_table_no_lock hacked_mysql_create_table_no_lock
74
int rea_create_table(Session *session,
75
TableIdentifier &identifier,
76
message::Table &table_proto,
77
HA_CREATE_INFO *create_info,
78
List<CreateField> &create_field,
79
uint32_t key_count,KEY *key_info);
81
int mysql_prepare_create_table(Session *session,
82
HA_CREATE_INFO *create_info,
83
message::Table &create_proto,
84
AlterInfo *alter_info,
87
KEY **key_info_buffer,
89
int select_field_count);
93
static uint32_t build_tmptable_filename(Session* session,
94
char *buff, size_t bufflen)
97
ostringstream path_str, post_tmpdir_str;
100
path_str << drizzle_tmpdir;
101
post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
102
post_tmpdir_str << session->thread_id << session->tmp_table++;
103
tmp= post_tmpdir_str.str();
105
transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
109
if (bufflen < path_str.str().length())
112
length= unpack_filename(buff, path_str.str().c_str());
117
static bool mysql_create_table_no_lock(Session *session,
118
const char *db, const char *table_name,
119
HA_CREATE_INFO *create_info,
120
message::Table *table_proto,
121
AlterInfo *alter_info,
122
bool internal_tmp_table,
123
uint32_t select_field_count,
126
char path[FN_REFLEN];
127
uint32_t path_length;
128
uint db_options, key_count;
129
KEY *key_info_buffer;
132
/* Check for duplicate fields and check type of table to create */
133
if (!alter_info->create_list.elements)
135
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
139
assert(strcmp(table_name,table_proto->name().c_str())==0);
140
//if (check_engine(session, table_name, table_proto, create_info))
142
db_options= create_info->table_options;
143
if (create_info->row_type == ROW_TYPE_DYNAMIC)
144
db_options|=HA_OPTION_PACK_RECORD;
146
/*if (!(file= create_info->db_type->getCursor((TableShare*) 0, session->mem_root)))
148
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
152
TableIdentifier ident(db, table_name, table_proto->type());
154
/* PMC - Done to avoid getting the partition handler by mistake! */
155
if (!(file= new (session->mem_root) ha_xtsys(pbxt_hton, *TableShare::getShare(ident))))
157
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
161
set_table_default_charset(create_info, (char*) db);
163
if (mysql_prepare_create_table(session,
169
&key_info_buffer, &key_count,
173
/* Check if table exists */
174
if (table_proto->type() == message::Table::TEMPORARY)
176
path_length= build_tmptable_filename(session, path, sizeof(path));
181
/* check if the table name contains FN_DEVCHAR when defined */
182
if (strchr(table_name, FN_DEVCHAR))
184
my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name);
188
std::string path_str;
189
path_length= build_table_filename(path_str, db, table_name, internal_tmp_table);
192
/* Check if table already exists */
193
if ((table_proto->type() == message::Table::TEMPORARY) &&
194
session->find_temporary_table(db, table_name))
198
create_info->table_existed= 1; // Mark that table existed
199
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
200
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
205
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
209
//pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
210
if (!internal_tmp_table && table_proto->type() != message::Table::TEMPORARY)
212
if (plugin::StorageEngine::getTableDefinition(*session,
220
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
221
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
223
create_info->table_existed= 1; // Mark that table existed
226
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
231
* We don't assert here, but check the result, because the table could be
232
* in the table definition cache and in the same time the .frm could be
233
* missing from the disk, in case of manual intervention which deletes
234
* the .frm file. The user has to use FLUSH TABLES; to clear the cache.
235
* Then she could create the table. This case is pretty obscure and
236
* therefore we don't introduce a new error message only for it.
238
if (TableShare::getShare(ident))
240
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
245
* Check that table with given name does not already
246
* exist in any storage engine. In such a case it should
247
* be discovered and the error ER_TABLE_EXISTS_ERROR be returned
248
* unless user specified CREATE TABLE IF EXISTS
249
* The LOCK_open mutex has been locked to make sure no
250
* one else is attempting to discover the table. Since
251
* it's not on disk as a frm file, no one could be using it!
253
if (table_proto->type() != message::Table::TEMPORARY)
255
bool create_if_not_exists = skip_existing;
257
std::string path_str;
258
uint32_t table_path_length;
260
table_path_length= build_table_filename(path_str, db, table_name, false);
262
int retcode= plugin::StorageEngine::getTableDefinition(*session,
269
/* Normal case, no table exists. we can go and create it */
272
if (create_if_not_exists)
275
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
276
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
278
create_info->table_existed= 1; // Mark that table existed
281
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
284
my_error(retcode, MYF(0),table_name);
289
session->set_proc_info("creating table");
290
create_info->table_existed= 0; // Mark that table is created
292
create_info->table_options=db_options;
294
if (rea_create_table(session, ident,
296
create_info, alter_info->create_list,
297
key_count, key_info_buffer))
300
if (table_proto->type() == message::Table::TEMPORARY)
302
/* Open table and put in temporary table list */
303
if (!(session->open_temporary_table(ident)))
305
(void) session->rm_temporary_table(ident);
311
* Don't write statement if:
312
* - It is an internal temporary table,
313
* - Row-based logging is used and it we are creating a temporary table, or
314
* - The binary log is not open.
315
* Otherwise, the statement shall be binlogged.
317
if (!internal_tmp_table &&
318
((table_proto->type() != message::Table::TEMPORARY)))
319
write_bin_log(session, session->getQueryString().c_str());
322
//pthread_mutex_unlock(&LOCK_open);
325
session->set_proc_info("After create");
331
///////////////////////////////
333
* Unfortunately I cannot use the standard mysql_create_table_no_lock() because it will lock "LOCK_open"
334
* which has already been locked while the server is performing table discovery. So I have added this hack
335
* in here to create my own version. The following macros will make the changes I need to get it to work.
336
* The actual function code has been copied here without changes.
338
* Its almost enough to make you want to cry. :(
340
//-----------------------------
342
#ifdef pthread_mutex_lock
343
#undef pthread_mutex_lock
346
#ifdef pthread_mutex_unlock
347
#undef pthread_mutex_unlock
350
#define mysql_create_table_no_lock hacked_mysql_create_table_no_lock
351
#define pthread_mutex_lock(l)
352
#define pthread_mutex_unlock(l)
354
#define check_engine(t, n, c) (0)
355
#define set_table_default_charset(t, c, d)
357
void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
358
uint32 *max_length, uint32 *tot_length);
360
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen);
361
uint build_table_filename(char *buff, size_t bufflen, const char *db,
362
const char *table_name, const char *ext, uint flags);
364
//////////////////////////////////////////////////////////
365
////// START OF CUT AND PASTES FROM sql_table.cc ////////
366
//////////////////////////////////////////////////////////
368
// sort_keys() cut and pasted directly from sql_table.cc.
369
static int sort_keys(KEY *a, KEY *b)
371
ulong a_flags= a->flags, b_flags= b->flags;
373
if (a_flags & HA_NOSAME)
375
if (!(b_flags & HA_NOSAME))
377
if ((a_flags ^ b_flags) & HA_NULL_PART_KEY)
379
/* Sort NOT NULL keys before other keys */
380
return (a_flags & HA_NULL_PART_KEY) ? 1 : -1;
382
if (a->name == primary_key_name)
384
if (b->name == primary_key_name)
386
/* Sort keys don't containing partial segments before others */
387
if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
388
return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1;
390
else if (b_flags & HA_NOSAME)
391
return 1; // Prefer b
393
if ((a_flags ^ b_flags) & HA_FULLTEXT)
395
return (a_flags & HA_FULLTEXT) ? 1 : -1;
398
Prefer original key order. usable_key_parts contains here
399
the original key position.
401
return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
402
(a->usable_key_parts > b->usable_key_parts) ? 1 :
406
// check_if_keyname_exists() cut and pasted directly from sql_table.cc.
408
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
410
for (KEY *key=start ; key != end ; key++)
411
if (!my_strcasecmp(system_charset_info,name,key->name))
416
// make_unique_key_name() cut and pasted directly from sql_table.cc.
418
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
420
char buff[MAX_FIELD_NAME],*buff_end;
422
if (!check_if_keyname_exists(field_name,start,end) &&
423
my_strcasecmp(system_charset_info,field_name,primary_key_name))
424
return (char*) field_name; // Use fieldname
425
buff_end=strmake(buff,field_name, sizeof(buff)-4);
428
Only 3 chars + '\0' left, so need to limit to 2 digit
429
This is ok as we can't have more than 100 keys anyway
431
for (uint i=2 ; i< 100; i++)
434
int10_to_str(i, buff_end+1, 10);
435
if (!check_if_keyname_exists(buff,start,end))
436
return sql_strdup(buff);
438
return (char*) "not_specified"; // Should never happen
442
// prepare_blob_field() cut and pasted directly from sql_table.cc.
443
static bool prepare_blob_field(THD *thd, Create_field *sql_field)
445
DBUG_ENTER("prepare_blob_field");
447
if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
448
!(sql_field->flags & BLOB_FLAG))
450
/* Convert long VARCHAR columns to TEXT or BLOB */
451
char warn_buff[MYSQL_ERRMSG_SIZE];
453
if (sql_field->def || (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
454
MODE_STRICT_ALL_TABLES)))
456
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
457
MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
460
sql_field->sql_type= MYSQL_TYPE_BLOB;
461
sql_field->flags|= BLOB_FLAG;
462
sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
463
(sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
464
(sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
465
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
469
if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
471
if (sql_field->sql_type == MYSQL_TYPE_BLOB)
473
/* The user has given a length to the blob column */
474
sql_field->sql_type= get_blob_type_from_length(sql_field->length);
475
sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
477
sql_field->length= 0;
482
//////////////////////////////
483
// mysql_prepare_create_table() cut and pasted directly from sql_table.cc.
485
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
486
Alter_info *alter_info,
489
handler *file, KEY **key_info_buffer,
490
uint *key_count, int select_field_count)
492
const char *key_name;
493
Create_field *sql_field,*dup_field;
494
uint field,null_fields,blob_columns,max_key_length;
495
ulong record_offset= 0;
497
KEY_PART_INFO *key_part_info;
498
int timestamps= 0, timestamps_with_niladic= 0;
500
int select_field_pos,auto_increment=0;
501
List_iterator<Create_field> it(alter_info->create_list);
502
List_iterator<Create_field> it2(alter_info->create_list);
503
uint total_uneven_bit_length= 0;
504
DBUG_ENTER("mysql_prepare_create_table");
506
select_field_pos= alter_info->create_list.elements - select_field_count;
507
null_fields=blob_columns=0;
508
create_info->varchar= 0;
509
max_key_length= file->max_key_length();
511
for (field_no=0; (sql_field=it++) ; field_no++)
513
CHARSET_INFO *save_cs;
516
Initialize length from its original value (number of characters),
517
which was set in the parser. This is necessary if we're
518
executing a prepared statement for the second time.
520
sql_field->length= sql_field->char_length;
521
if (!sql_field->charset)
522
sql_field->charset= create_info->default_table_charset;
524
table_charset is set in ALTER TABLE if we want change character set
525
for all varchar/char columns.
526
But the table charset must not affect the BLOB fields, so don't
527
allow to change my_charset_bin to somethig else.
529
if (create_info->table_charset && sql_field->charset != &my_charset_bin)
530
sql_field->charset= create_info->table_charset;
532
save_cs= sql_field->charset;
533
if ((sql_field->flags & BINCMP_FLAG) &&
534
!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
535
MY_CS_BINSORT,MYF(0))))
538
strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
539
STRING_WITH_LEN("_bin"));
540
my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
545
Convert the default value from client character
546
set into the column character set if necessary.
548
if (sql_field->def &&
549
save_cs != sql_field->def->collation.collation &&
550
(sql_field->sql_type == MYSQL_TYPE_VAR_STRING ||
551
sql_field->sql_type == MYSQL_TYPE_STRING ||
552
sql_field->sql_type == MYSQL_TYPE_SET ||
553
sql_field->sql_type == MYSQL_TYPE_ENUM))
556
Starting from 5.1 we work here with a copy of Create_field
557
created by the caller, not with the instance that was
558
originally created during parsing. It's OK to create
559
a temporary item and initialize with it a member of the
560
copy -- this item will be thrown away along with the copy
561
at the end of execution, and thus not introduce a dangling
562
pointer in the parsed tree of a prepared statement or a
563
stored procedure statement.
565
sql_field->def= sql_field->def->safe_charset_converter(save_cs);
567
if (sql_field->def == NULL)
569
/* Could not convert */
570
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
575
if (sql_field->sql_type == MYSQL_TYPE_SET ||
576
sql_field->sql_type == MYSQL_TYPE_ENUM)
579
CHARSET_INFO *cs= sql_field->charset;
580
TYPELIB *interval= sql_field->interval;
583
Create typelib from interval_list, and if necessary
584
convert strings from client character set to the
585
column character set.
590
Create the typelib in runtime memory - we will free the
591
occupied memory at the same time when we free this
592
sql_field -- at the end of execution.
594
interval= sql_field->interval= typelib(thd->mem_root,
595
sql_field->interval_list);
596
List_iterator<String> int_it(sql_field->interval_list);
599
int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
602
DBUG_ASSERT(comma_length > 0);
603
for (uint i= 0; (tmp= int_it++); i++)
606
if (String::needs_conversion(tmp->length(), tmp->charset(),
610
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
611
interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
613
interval->type_lengths[i]= conv.length();
616
// Strip trailing spaces.
617
lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
618
interval->type_lengths[i]);
619
interval->type_lengths[i]= lengthsp;
620
((uchar *)interval->type_names[i])[lengthsp]= '\0';
621
if (sql_field->sql_type == MYSQL_TYPE_SET)
623
if (cs->coll->instr(cs, interval->type_names[i],
624
interval->type_lengths[i],
625
comma_buf, comma_length, NULL, 0))
627
my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr());
632
sql_field->interval_list.empty(); // Don't need interval_list anymore
635
if (sql_field->sql_type == MYSQL_TYPE_SET)
638
if (sql_field->def != NULL)
643
String str, *def= sql_field->def->val_str(&str);
644
if (def == NULL) /* SQL "NULL" maps to NULL */
646
if ((sql_field->flags & NOT_NULL_FLAG) != 0)
648
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
652
/* else, NULL is an allowed value */
653
(void) find_set(interval, NULL, 0,
654
cs, ¬_used, ¬_used2, ¬_found);
658
(void) find_set(interval, def->ptr(), def->length(),
659
cs, ¬_used, ¬_used2, ¬_found);
664
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
668
calculate_interval_lengths(cs, interval, &dummy, &field_length);
669
sql_field->length= field_length + (interval->count - 1);
671
else /* MYSQL_TYPE_ENUM */
674
DBUG_ASSERT(sql_field->sql_type == MYSQL_TYPE_ENUM);
675
if (sql_field->def != NULL)
677
String str, *def= sql_field->def->val_str(&str);
678
if (def == NULL) /* SQL "NULL" maps to NULL */
680
if ((sql_field->flags & NOT_NULL_FLAG) != 0)
682
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
686
/* else, the defaults yield the correct length for NULLs. */
690
def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
691
if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
693
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
698
calculate_interval_lengths(cs, interval, &field_length, &dummy);
699
sql_field->length= field_length;
701
set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
704
if (sql_field->sql_type == MYSQL_TYPE_BIT)
706
sql_field->pack_flag= FIELDFLAG_NUMBER;
707
if (file->ha_table_flags() & HA_CAN_BIT_FIELD)
708
total_uneven_bit_length+= sql_field->length & 7;
710
sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
713
sql_field->create_length_to_internal_length();
714
if (prepare_blob_field(thd, sql_field))
717
if (!(sql_field->flags & NOT_NULL_FLAG))
720
if (check_column_name(sql_field->field_name))
722
my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
726
/* Check if we have used the same field name before */
727
for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
729
if (my_strcasecmp(system_charset_info,
730
sql_field->field_name,
731
dup_field->field_name) == 0)
734
If this was a CREATE ... SELECT statement, accept a field
735
redefinition if we are changing a field in the SELECT part
737
if (field_no < select_field_pos || dup_no >= select_field_pos)
739
my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
744
/* Field redefined */
745
sql_field->def= dup_field->def;
746
sql_field->sql_type= dup_field->sql_type;
747
sql_field->charset= (dup_field->charset ?
749
create_info->default_table_charset);
750
sql_field->length= dup_field->char_length;
751
sql_field->pack_length= dup_field->pack_length;
752
sql_field->key_length= dup_field->key_length;
753
sql_field->decimals= dup_field->decimals;
754
sql_field->create_length_to_internal_length();
755
sql_field->unireg_check= dup_field->unireg_check;
757
We're making one field from two, the result field will have
758
dup_field->flags as flags. If we've incremented null_fields
759
because of sql_field->flags, decrement it back.
761
if (!(sql_field->flags & NOT_NULL_FLAG))
763
sql_field->flags= dup_field->flags;
764
sql_field->interval= dup_field->interval;
765
it2.remove(); // Remove first (create) definition
771
/* Don't pack rows in old tables if the user has requested this */
772
if ((sql_field->flags & BLOB_FLAG) ||
773
(sql_field->sql_type == MYSQL_TYPE_VARCHAR &&
774
create_info->row_type != ROW_TYPE_FIXED))
775
(*db_options)|= HA_OPTION_PACK_RECORD;
779
/* record_offset will be increased with 'length-of-null-bits' later */
781
null_fields+= total_uneven_bit_length;
784
while ((sql_field=it++))
786
DBUG_ASSERT(sql_field->charset != 0);
788
if (prepare_create_field(sql_field, &blob_columns,
789
×tamps, ×tamps_with_niladic,
790
file->ha_table_flags()))
792
if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
793
create_info->varchar= TRUE;
794
sql_field->offset= record_offset;
795
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
797
record_offset+= sql_field->pack_length;
799
if (timestamps_with_niladic > 1)
801
my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
802
ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
805
if (auto_increment > 1)
807
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
810
if (auto_increment &&
811
(file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
813
my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
814
ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
818
if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
820
my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
827
List_iterator<Key> key_iterator(alter_info->key_list);
828
List_iterator<Key> key_iterator2(alter_info->key_list);
829
uint key_parts=0, fk_key_count=0;
830
bool primary_key=0,unique_key=0;
832
uint tmp, key_number;
833
/* special marker for keys to be ignored */
834
static char ignore_key[1];
836
/* Calculate number of key segements */
839
while ((key=key_iterator++))
841
DBUG_PRINT("info", ("key name: '%s' type: %d", key->DOT_STR(name) ? key->DOT_STR(name) :
842
"(none)" , key->type));
843
LEX_STRING key_name_str;
844
if (key->type == Key::FOREIGN_KEY)
847
Foreign_key *fk_key= (Foreign_key*) key;
848
if (fk_key->ref_columns.elements &&
849
fk_key->ref_columns.elements != fk_key->columns.elements)
851
my_error(ER_WRONG_FK_DEF, MYF(0),
852
(fk_key->DOT_STR(name) ? fk_key->DOT_STR(name) : "foreign key without name"),
853
ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
859
tmp=file->max_key_parts();
860
if (key->columns.elements > tmp)
862
my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
865
key_name_str.str= (char*) key->DOT_STR(name);
866
key_name_str.length= key->DOT_STR(name) ? strlen(key->DOT_STR(name)) : 0;
867
if (check_string_char_length(&key_name_str, "", NAME_CHAR_LEN,
868
system_charset_info, 1))
870
my_error(ER_TOO_LONG_IDENT, MYF(0), key->DOT_STR(name));
873
key_iterator2.rewind ();
874
if (key->type != Key::FOREIGN_KEY)
876
while ((key2 = key_iterator2++) != key)
879
foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is
880
'generated', and a generated key is a prefix of the other key.
881
Then we do not need the generated shorter key.
883
if ((key2->type != Key::FOREIGN_KEY &&
884
key2->DOT_STR(name) != ignore_key &&
885
!foreign_key_prefix(key, key2)))
887
/* TODO: issue warning message */
888
/* mark that the generated key should be ignored */
889
if (!key2->generated ||
890
(key->generated && key->columns.elements <
891
key2->columns.elements))
892
key->DOT_STR(name)= ignore_key;
895
key2->DOT_STR(name)= ignore_key;
896
key_parts-= key2->columns.elements;
903
if (key->DOT_STR(name) != ignore_key)
904
key_parts+=key->columns.elements;
907
if (key->DOT_STR(name) && !tmp_table && (key->type != Key::PRIMARY) &&
908
!my_strcasecmp(system_charset_info,key->DOT_STR(name),primary_key_name))
910
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->DOT_STR(name));
914
tmp=file->max_keys();
915
if (*key_count > tmp)
917
my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
921
(*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
922
key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
923
if (!*key_info_buffer || ! key_part_info)
924
DBUG_RETURN(TRUE); // Out of memory
926
key_iterator.rewind();
928
for (; (key=key_iterator++) ; key_number++)
931
Key_part_spec *column;
933
if (key->DOT_STR(name) == ignore_key)
935
/* ignore redundant keys */
938
while (key && key->DOT_STR(name) == ignore_key);
948
key_info->flags= HA_FULLTEXT;
949
if ((key_info->parser_name= &key->key_create_info.parser_name)->str)
950
key_info->flags|= HA_USES_PARSER;
952
key_info->parser_name= 0;
956
key_info->flags= HA_SPATIAL;
959
my_error(ER_FEATURE_DISABLED, MYF(0),
960
sym_group_geom.name, sym_group_geom.needed_define);
963
case Key::FOREIGN_KEY:
964
key_number--; // Skip this key
967
key_info->flags = HA_NOSAME;
971
key_info->flags|= HA_GENERATED_KEY;
973
key_info->key_parts=(uint8) key->columns.elements;
974
key_info->key_part=key_part_info;
975
key_info->usable_key_parts= key_number;
976
key_info->algorithm= key->key_create_info.algorithm;
978
if (key->type == Key::FULLTEXT)
980
if (!(file->ha_table_flags() & HA_CAN_FULLTEXT))
982
my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT),
988
Make SPATIAL to be RTREE by default
989
SPATIAL only on BLOB or at least BINARY, this
990
actually should be replaced by special GEOM type
991
in near future when new frm file is ready
992
checking for proper key parts number:
995
/* TODO: Add proper checks if handler supports key_type and algorithm */
996
if (key_info->flags & HA_SPATIAL)
998
if (!(file->ha_table_flags() & HA_CAN_RTREEKEYS))
1000
my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS),
1004
if (key_info->key_parts != 1)
1006
my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
1010
else if (key_info->algorithm == HA_KEY_ALG_RTREE)
1012
#ifdef HAVE_RTREE_KEYS
1013
if ((key_info->key_parts & 1) == 1)
1015
my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX");
1018
/* TODO: To be deleted */
1019
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX");
1022
my_error(ER_FEATURE_DISABLED, MYF(0),
1023
sym_group_rtree.name, sym_group_rtree.needed_define);
1028
/* Take block size from key part or table part */
1030
TODO: Add warning if block size changes. We can't do it here, as
1031
this may depend on the size of the key
1033
key_info->block_size= (key->key_create_info.block_size ?
1034
key->key_create_info.block_size :
1035
create_info->key_block_size);
1037
if (key_info->block_size)
1038
key_info->flags|= HA_USES_BLOCK_SIZE;
1040
List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
1041
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
1042
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
1045
Key_part_spec *dup_column;
1049
while ((sql_field=it++) &&
1050
my_strcasecmp(system_charset_info,
1051
column->DOT_STR(field_name),
1052
sql_field->field_name))
1056
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
1059
while ((dup_column= cols2++) != column)
1061
if (!my_strcasecmp(system_charset_info,
1062
column->DOT_STR(field_name), dup_column->DOT_STR(field_name)))
1064
my_printf_error(ER_DUP_FIELDNAME,
1065
ER(ER_DUP_FIELDNAME),MYF(0),
1066
column->field_name);
1071
if (key->type == Key::FULLTEXT)
1073
if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
1074
sql_field->sql_type != MYSQL_TYPE_VARCHAR &&
1075
!f_is_blob(sql_field->pack_flag)) ||
1076
sql_field->charset == &my_charset_bin ||
1077
sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
1078
(ft_key_charset && sql_field->charset != ft_key_charset))
1080
my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name);
1083
ft_key_charset=sql_field->charset;
1085
for fulltext keys keyseg length is 1 for blobs (it's ignored in ft
1086
code anyway, and 0 (set to column width later) for char's. it has
1087
to be correct col width for char's, as char data are not prefixed
1088
with length (unlike blobs, where ft code takes data length from a
1089
data prefix, ignoring column->length).
1091
column->length=test(f_is_blob(sql_field->pack_flag));
1095
column->length*= sql_field->charset->mbmaxlen;
1097
if (key->type == Key::SPATIAL && column->length)
1099
my_error(ER_WRONG_SUB_KEY, MYF(0));
1103
if (f_is_blob(sql_field->pack_flag) ||
1104
(f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
1106
if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
1108
my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name);
1111
if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
1114
if (!column->length)
1116
my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name);
1121
if (key->type == Key::SPATIAL)
1123
if (!column->length)
1126
4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
1127
Lately we'll extend this code to support more dimensions
1129
column->length= 4*sizeof(double);
1133
if (!(sql_field->flags & NOT_NULL_FLAG))
1135
if (key->type == Key::PRIMARY)
1137
/* Implicitly set primary key fields to NOT NULL for ISO conf. */
1138
sql_field->flags|= NOT_NULL_FLAG;
1139
sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
1144
key_info->flags|= HA_NULL_PART_KEY;
1145
if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
1147
my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name);
1150
if (key->type == Key::SPATIAL)
1152
my_message(ER_SPATIAL_CANT_HAVE_NULL,
1153
ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
1158
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1160
if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
1161
auto_increment--; // Field is used
1165
key_part_info->fieldnr= field;
1166
key_part_info->offset= (uint16) sql_field->offset;
1167
key_part_info->key_type=sql_field->pack_flag;
1168
length= sql_field->key_length;
1172
if (f_is_blob(sql_field->pack_flag))
1174
if ((length=column->length) > max_key_length ||
1175
length > file->max_key_part_length())
1177
length=min(max_key_length, file->max_key_part_length());
1178
if (key->type == Key::MULTIPLE)
1180
/* not a critical problem */
1181
char warn_buff[MYSQL_ERRMSG_SIZE];
1182
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
1184
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1185
ER_TOO_LONG_KEY, warn_buff);
1186
/* Align key length to multibyte char boundary */
1187
length-= length % sql_field->charset->mbmaxlen;
1191
my_error(ER_TOO_LONG_KEY,MYF(0),length);
1196
else if (!f_is_geom(sql_field->pack_flag) &&
1197
(column->length > length ||
1198
!Field::type_can_have_key_part (sql_field->sql_type) ||
1199
((f_is_packed(sql_field->pack_flag) ||
1200
((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
1201
(key_info->flags & HA_NOSAME))) &&
1202
column->length != length)))
1204
my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1207
else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
1208
length=column->length;
1210
else if (length == 0)
1212
my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name);
1215
if (length > file->max_key_part_length() && key->type != Key::FULLTEXT)
1217
length= file->max_key_part_length();
1218
if (key->type == Key::MULTIPLE)
1220
/* not a critical problem */
1221
char warn_buff[MYSQL_ERRMSG_SIZE];
1222
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
1224
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1225
ER_TOO_LONG_KEY, warn_buff);
1226
/* Align key length to multibyte char boundary */
1227
length-= length % sql_field->charset->mbmaxlen;
1231
my_error(ER_TOO_LONG_KEY,MYF(0),length);
1235
key_part_info->length=(uint16) length;
1236
/* Use packed keys for long strings on the first column */
1237
if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
1238
(length >= KEY_DEFAULT_PACK_LENGTH &&
1239
(sql_field->sql_type == MYSQL_TYPE_STRING ||
1240
sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
1241
sql_field->pack_flag & FIELDFLAG_BLOB)))
1243
if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
1244
sql_field->sql_type == MYSQL_TYPE_VARCHAR)
1245
key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1247
key_info->flags|= HA_PACK_KEY;
1249
/* Check if the key segment is partial, set the key flag accordingly */
1250
if (length != sql_field->key_length)
1251
key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
1256
/* Create the key name based on the first column (if not given) */
1259
if (key->type == Key::PRIMARY)
1263
my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
1267
key_name=primary_key_name;
1270
else if (!(key_name = key->DOT_STR(name)))
1271
key_name=make_unique_key_name(sql_field->field_name,
1272
*key_info_buffer, key_info);
1273
if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
1275
my_error(ER_DUP_KEYNAME, MYF(0), key_name);
1278
key_info->name=(char*) key_name;
1281
if (!key_info->name || check_column_name(key_info->name))
1283
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1286
if (!(key_info->flags & HA_NULL_PART_KEY))
1288
key_info->key_length=(uint16) key_length;
1289
if (key_length > max_key_length && key->type != Key::FULLTEXT)
1291
my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1296
if (!unique_key && !primary_key &&
1297
(file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1299
my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1302
if (auto_increment > 0)
1304
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1307
/* Sort keys in optimized order */
1308
my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
1309
(qsort_cmp) sort_keys);
1310
create_info->null_bits= null_fields;
1314
while ((sql_field=it++))
1316
Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1318
if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
1320
sql_field->sql_type == MYSQL_TYPE_TIMESTAMP &&
1321
(sql_field->flags & NOT_NULL_FLAG) &&
1322
(type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1325
An error should be reported if:
1326
- NO_ZERO_DATE SQL mode is active;
1327
- there is no explicit DEFAULT clause (default column value);
1328
- this is a TIMESTAMP column;
1329
- the column is not NULL;
1330
- this is not the DEFAULT CURRENT_TIMESTAMP column.
1332
In other words, an error should be reported if
1333
- NO_ZERO_DATE SQL mode is active;
1334
- the column definition is equivalent to
1335
'column_name TIMESTAMP DEFAULT 0'.
1338
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
1346
//////////////////////////////
1347
// mysql_create_table_no_lock() cut and pasted directly from sql_table.cc. (I did make is static after copying it.)
1349
static bool mysql_create_table_no_lock(THD *thd,
1350
const char *db, const char *table_name,
1351
HA_CREATE_INFO *create_info,
1352
Alter_info *alter_info,
1353
bool internal_tmp_table,
1354
uint select_field_count)
1356
char path[FN_REFLEN];
1359
uint db_options, key_count;
1360
KEY *key_info_buffer;
1363
DBUG_ENTER("mysql_create_table_no_lock");
1364
DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d",
1365
db, table_name, internal_tmp_table));
1368
/* Check for duplicate fields and check type of table to create */
1369
if (!alter_info->create_list.elements)
1371
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1375
if (check_engine(thd, table_name, create_info))
1377
db_options= create_info->table_options;
1378
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1379
db_options|=HA_OPTION_PACK_RECORD;
1380
alias= table_case_name(create_info, table_name);
1382
/* PMC - Done to avoid getting the partition handler by mistake! */
1383
if (!(file= new (thd->mem_root) ha_xtsys(pbxt_hton, NULL)))
1385
mem_alloc_error(sizeof(handler));
1389
set_table_default_charset(thd, create_info, (char*) db);
1391
if (mysql_prepare_create_table(thd, create_info, alter_info,
1394
&key_info_buffer, &key_count,
1395
select_field_count))
1398
/* Check if table exists */
1399
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1401
path_length= build_tmptable_filename(thd, path, sizeof(path));
1402
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
1407
/* check if the table name contains FN_DEVCHAR when defined */
1408
if (strchr(alias, FN_DEVCHAR))
1410
my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
1414
path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
1415
internal_tmp_table ? FN_IS_TMP : 0);
1418
/* Check if table already exists */
1419
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1420
find_temporary_table(thd, db, table_name))
1422
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1424
create_info->table_existed= 1; // Mark that table existed
1425
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1426
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1431
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
1435
pthread_mutex_lock(&LOCK_open);
1436
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1438
if (!access(path,F_OK))
1440
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1442
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1443
goto unlock_and_end;
1446
We don't assert here, but check the result, because the table could be
1447
in the table definition cache and in the same time the .frm could be
1448
missing from the disk, in case of manual intervention which deletes
1449
the .frm file. The user has to use FLUSH TABLES; to clear the cache.
1450
Then she could create the table. This case is pretty obscure and
1451
therefore we don't introduce a new error message only for it.
1453
if (get_cached_table_share(db, alias))
1455
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1456
goto unlock_and_end;
1461
Check that table with given name does not already
1462
exist in any storage engine. In such a case it should
1463
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1464
unless user specified CREATE TABLE IF EXISTS
1465
The LOCK_open mutex has been locked to make sure no
1466
one else is attempting to discover the table. Since
1467
it's not on disk as a frm file, no one could be using it!
1469
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1471
bool create_if_not_exists =
1472
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
1473
int retcode = ha_table_exists_in_engine(thd, db, table_name);
1474
DBUG_PRINT("info", ("exists_in_engine: %u",retcode));
1477
case HA_ERR_NO_SUCH_TABLE:
1478
/* Normal case, no table exists. we can go and create it */
1480
case HA_ERR_TABLE_EXIST:
1481
DBUG_PRINT("info", ("Table existed in handler"));
1483
if (create_if_not_exists)
1485
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1486
goto unlock_and_end;
1489
DBUG_PRINT("info", ("error: %u from storage engine", retcode));
1490
my_error(retcode, MYF(0),table_name);
1491
goto unlock_and_end;
1495
thd_proc_info(thd, "creating table");
1496
create_info->table_existed= 0; // Mark that table is created
1498
create_info->table_options=db_options;
1500
path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
1501
if (rea_create_table(thd, path, db, table_name,
1502
create_info, alter_info->create_list,
1503
key_count, key_info_buffer, file))
1504
goto unlock_and_end;
1506
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1508
/* Open table and put in temporary table list */
1509
#if MYSQL_VERSION_ID >= 50404
1510
if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
1512
if (!(open_temporary_table(thd, path, db, table_name, 1)))
1515
#if MYSQL_VERSION_ID >= 50404
1516
(void) rm_temporary_table(create_info->db_type, path, false);
1518
(void) rm_temporary_table(create_info->db_type, path);
1520
goto unlock_and_end;
1522
thd->thread_specific_used= TRUE;
1526
Don't write statement if:
1527
- It is an internal temporary table,
1528
- Row-based logging is used and it we are creating a temporary table, or
1529
- The binary log is not open.
1530
Otherwise, the statement shall be binlogged.
1533
* Firstly we had a compile problem with MySQL 5.1.42 and
1534
* the write_bin_log() call below:
1535
* discover_xt.cc:1259: error: argument of type 'char* (Statement::)()' does not match 'const char*'
1537
* And secondly, we should no write the BINLOG anyway because this is
1538
* an internal PBXT system table.
1540
* So I am just commenting out the code altogether.
1541
if (!internal_tmp_table &&
1542
(!thd->current_stmt_binlog_row_based ||
1543
(thd->current_stmt_binlog_row_based &&
1544
!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1545
write_bin_log(thd, TRUE, thd->query, thd->query_length);
1549
pthread_mutex_unlock(&LOCK_open);
1552
thd_proc_info(thd, "After create");
1558
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1559
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1561
create_info->table_existed= 1; // Mark that table existed
1562
goto unlock_and_end;
1565
////////////////////////////////////////////////////////
1566
////// END OF CUT AND PASTES FROM sql_table.cc ////////
1567
////////////////////////////////////////////////////////
1570
#endif // LOCK_OPEN_HACK_REQUIRED
1572
//------------------------------
1573
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)
1576
#define MYLEX_CREATE_INFO create_info
1578
#define MYLEX_CREATE_INFO mylex.create_info
1582
drizzled::statement::AlterTable *stmt = new drizzled::statement::AlterTable(thd);
1583
HA_CREATE_INFO create_info;
1584
//AlterInfo alter_info;
1585
drizzled::message::Table table_proto;
1587
static const char *ext = ".dfe";
1588
static const int ext_len = 4;
1590
table_proto.mutable_engine()->mutable_name()->assign("PBXT");
1592
static const char *ext = ".frm";
1593
static const int ext_len = 4;
1596
char field_length_buffer[12], *field_length_ptr;
1597
LEX *save_lex= thd->lex, mylex;
1599
memset(&MYLEX_CREATE_INFO, 0, sizeof(HA_CREATE_INFO));
1604
mylex.statement = stmt;
1607
/* setup the create info */
1608
MYLEX_CREATE_INFO.db_type = hton;
1611
mylex.create_info.frm_only = 1;
1613
MYLEX_CREATE_INFO.default_table_charset = system_charset_info;
1615
/* setup the column info. */
1616
while (info->field_name) {
1617
LEX_STRING field_name, comment;
1618
field_name.str = (char*)(info->field_name);
1619
field_name.length = strlen(info->field_name);
1621
comment.str = (char*)(info->comment);
1622
comment.length = strlen(info->comment);
1624
if (info->field_length) {
1625
sprintf(field_length_buffer, "%d", info->field_length);
1626
field_length_ptr = field_length_buffer;
1628
field_length_ptr = NULL;
1631
if (add_field_to_list(thd, &field_name, info->field_type, field_length_ptr, info->field_decimal_length,
1633
COLUMN_FORMAT_TYPE_FIXED,
1634
NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
1635
NULL /*interval_list*/, info->field_charset))
1637
if (add_field_to_list(thd, &field_name, info->field_type, field_length_ptr, info->field_decimal_length,
1639
#if MYSQL_VERSION_ID >= 50404
1641
COLUMN_FORMAT_TYPE_FIXED,
1643
NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
1644
NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/))
1652
if (skip_existing) {
1653
size_t db_len = strlen(db);
1654
size_t name_len = strlen(name);
1655
size_t len = db_len + 1 + name_len + ext_len + 1;
1656
char *path = (char *)xt_malloc_ns(len);
1657
memcpy(path, db, db_len);
1658
memcpy(path + db_len + 1, name, name_len);
1659
memcpy(path + db_len + 1 + name_len, ext, ext_len);
1660
path[db_len] = XT_DIR_CHAR;
1661
path[len - 1] = '\0';
1662
xtBool exists = xt_fs_exists(path);
1668
/* Create an internal temp table */
1670
table_proto.set_name(name);
1671
table_proto.set_type(drizzled::message::Table::STANDARD);
1672
table_proto.set_schema(db);
1673
table_proto.set_creation_timestamp(time(NULL));
1674
table_proto.set_update_timestamp(time(NULL));
1675
if (mysql_create_table_no_lock(thd, db, name, &create_info, &table_proto, &stmt->alter_info, 1, 0, skip_existing))
1678
if (mysql_create_table_no_lock(thd, db, name, &mylex.create_info, &mylex.alter_info, 1, 0))
1687
thd->lex = save_lex;