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"
29
#include "mysql_priv.h"
30
#include "item_create.h"
33
#include <drizzled/session.h>
34
#include <drizzled/sql_base.h>
35
#include <drizzled/statement/alter_table.h>
36
#include <drizzled/sql_table.h>
40
extern pid_t current_pid;
42
size_t unpack_filename(char * to, const char *from);
45
using namespace drizzled;
46
using namespace drizzled::internal;
49
#include "strutil_xt.h"
51
#include "discover_xt.h"
55
#if MYSQL_VERSION_ID >= 50404
56
#define DOT_STR(x) x.str
63
#define LOCK_OPEN_HACK_REQUIRED
66
#ifdef LOCK_OPEN_HACK_REQUIRED
69
using namespace drizzled;
72
#define mysql_create_table_no_lock hacked_mysql_create_table_no_lock
76
int rea_create_table(Session *session,
77
TableIdentifier &identifier,
78
message::Table &table_proto,
79
HA_CREATE_INFO *create_info,
80
List<CreateField> &create_field,
81
uint32_t key_count,KEY *key_info);
83
int mysql_prepare_create_table(Session *session,
84
HA_CREATE_INFO *create_info,
85
message::Table &create_proto,
86
AlterInfo *alter_info,
89
KEY **key_info_buffer,
91
int select_field_count);
95
static uint32_t build_tmptable_filename(Session* session,
96
char *buff, size_t bufflen)
99
ostringstream path_str, post_tmpdir_str;
102
path_str << drizzle_tmpdir;
103
post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
104
post_tmpdir_str << session->thread_id << session->tmp_table++;
105
tmp= post_tmpdir_str.str();
107
transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
111
if (bufflen < path_str.str().length())
114
length= unpack_filename(buff, path_str.str().c_str());
119
static bool mysql_create_table_no_lock(Session *session,
120
const char *db, const char *table_name,
121
HA_CREATE_INFO *create_info,
122
message::Table *table_proto,
123
AlterInfo *alter_info,
124
bool internal_tmp_table,
125
uint32_t select_field_count,
128
char path[FN_REFLEN];
129
uint32_t path_length;
130
uint db_options, key_count;
131
KEY *key_info_buffer;
134
/* Check for duplicate fields and check type of table to create */
135
if (!alter_info->create_list.elements)
137
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
141
assert(strcmp(table_name,table_proto->name().c_str())==0);
142
//if (check_engine(session, table_name, table_proto, create_info))
144
db_options= create_info->table_options;
145
if (create_info->row_type == ROW_TYPE_DYNAMIC)
146
db_options|=HA_OPTION_PACK_RECORD;
148
/*if (!(file= create_info->db_type->getCursor((TableShare*) 0, session->mem_root)))
150
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
154
TableIdentifier ident(db, table_name, table_proto->type());
156
/* PMC - Done to avoid getting the partition handler by mistake! */
157
if (!(file= new (session->mem_root) ha_xtsys(pbxt_hton, *TableShare::getShare(ident))))
159
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
163
set_table_default_charset(create_info, (char*) db);
165
if (mysql_prepare_create_table(session,
171
&key_info_buffer, &key_count,
175
/* Check if table exists */
176
if (table_proto->type() == message::Table::TEMPORARY)
178
path_length= build_tmptable_filename(session, path, sizeof(path));
183
/* check if the table name contains FN_DEVCHAR when defined */
184
if (strchr(table_name, FN_DEVCHAR))
186
my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name);
190
std::string path_str;
191
path_length= build_table_filename(path_str, db, table_name, internal_tmp_table);
194
/* Check if table already exists */
195
if ((table_proto->type() == message::Table::TEMPORARY) &&
196
session->find_temporary_table(db, table_name))
200
create_info->table_existed= 1; // Mark that table existed
201
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
202
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
207
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
211
//pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
212
if (!internal_tmp_table && table_proto->type() != message::Table::TEMPORARY)
214
if (plugin::StorageEngine::getTableDefinition(*session,
222
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
223
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
225
create_info->table_existed= 1; // Mark that table existed
228
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
233
* We don't assert here, but check the result, because the table could be
234
* in the table definition cache and in the same time the .frm could be
235
* missing from the disk, in case of manual intervention which deletes
236
* the .frm file. The user has to use FLUSH TABLES; to clear the cache.
237
* Then she could create the table. This case is pretty obscure and
238
* therefore we don't introduce a new error message only for it.
240
if (TableShare::getShare(ident))
242
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
247
* Check that table with given name does not already
248
* exist in any storage engine. In such a case it should
249
* be discovered and the error ER_TABLE_EXISTS_ERROR be returned
250
* unless user specified CREATE TABLE IF EXISTS
251
* The LOCK_open mutex has been locked to make sure no
252
* one else is attempting to discover the table. Since
253
* it's not on disk as a frm file, no one could be using it!
255
if (table_proto->type() != message::Table::TEMPORARY)
257
bool create_if_not_exists = skip_existing;
259
std::string path_str;
260
uint32_t table_path_length;
262
table_path_length= build_table_filename(path_str, db, table_name, false);
264
int retcode= plugin::StorageEngine::getTableDefinition(*session,
271
/* Normal case, no table exists. we can go and create it */
274
if (create_if_not_exists)
277
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
278
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
280
create_info->table_existed= 1; // Mark that table existed
283
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
286
my_error(retcode, MYF(0),table_name);
291
session->set_proc_info("creating table");
292
create_info->table_existed= 0; // Mark that table is created
294
create_info->table_options=db_options;
296
if (rea_create_table(session, ident,
298
create_info, alter_info->create_list,
299
key_count, key_info_buffer))
302
if (table_proto->type() == message::Table::TEMPORARY)
304
/* Open table and put in temporary table list */
305
if (!(session->open_temporary_table(ident)))
307
(void) session->rm_temporary_table(ident);
313
* Don't write statement if:
314
* - It is an internal temporary table,
315
* - Row-based logging is used and it we are creating a temporary table, or
316
* - The binary log is not open.
317
* Otherwise, the statement shall be binlogged.
319
if (!internal_tmp_table &&
320
((table_proto->type() != message::Table::TEMPORARY)))
321
write_bin_log(session, session->getQueryString().c_str());
324
//pthread_mutex_unlock(&LOCK_open);
327
session->set_proc_info("After create");
333
///////////////////////////////
335
* Unfortunately I cannot use the standard mysql_create_table_no_lock() because it will lock "LOCK_open"
336
* which has already been locked while the server is performing table discovery. So I have added this hack
337
* in here to create my own version. The following macros will make the changes I need to get it to work.
338
* The actual function code has been copied here without changes.
340
* Its almost enough to make you want to cry. :(
342
//-----------------------------
344
#ifdef pthread_mutex_lock
345
#undef pthread_mutex_lock
348
#ifdef pthread_mutex_unlock
349
#undef pthread_mutex_unlock
352
#define mysql_create_table_no_lock hacked_mysql_create_table_no_lock
353
#define pthread_mutex_lock(l)
354
#define pthread_mutex_unlock(l)
356
#define check_engine(t, n, c) (0)
357
#define set_table_default_charset(t, c, d)
359
void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
360
uint32 *max_length, uint32 *tot_length);
362
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen);
363
uint build_table_filename(char *buff, size_t bufflen, const char *db,
364
const char *table_name, const char *ext, uint flags);
366
//////////////////////////////////////////////////////////
367
////// START OF CUT AND PASTES FROM sql_table.cc ////////
368
//////////////////////////////////////////////////////////
370
// sort_keys() cut and pasted directly from sql_table.cc.
371
static int sort_keys(KEY *a, KEY *b)
373
ulong a_flags= a->flags, b_flags= b->flags;
375
if (a_flags & HA_NOSAME)
377
if (!(b_flags & HA_NOSAME))
379
if ((a_flags ^ b_flags) & HA_NULL_PART_KEY)
381
/* Sort NOT NULL keys before other keys */
382
return (a_flags & HA_NULL_PART_KEY) ? 1 : -1;
384
if (a->name == primary_key_name)
386
if (b->name == primary_key_name)
388
/* Sort keys don't containing partial segments before others */
389
if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
390
return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1;
392
else if (b_flags & HA_NOSAME)
393
return 1; // Prefer b
395
if ((a_flags ^ b_flags) & HA_FULLTEXT)
397
return (a_flags & HA_FULLTEXT) ? 1 : -1;
400
Prefer original key order. usable_key_parts contains here
401
the original key position.
403
return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
404
(a->usable_key_parts > b->usable_key_parts) ? 1 :
408
// check_if_keyname_exists() cut and pasted directly from sql_table.cc.
410
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
412
for (KEY *key=start ; key != end ; key++)
413
if (!my_strcasecmp(system_charset_info,name,key->name))
418
// make_unique_key_name() cut and pasted directly from sql_table.cc.
420
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
422
char buff[MAX_FIELD_NAME],*buff_end;
424
if (!check_if_keyname_exists(field_name,start,end) &&
425
my_strcasecmp(system_charset_info,field_name,primary_key_name))
426
return (char*) field_name; // Use fieldname
427
buff_end=strmake(buff,field_name, sizeof(buff)-4);
430
Only 3 chars + '\0' left, so need to limit to 2 digit
431
This is ok as we can't have more than 100 keys anyway
433
for (uint i=2 ; i< 100; i++)
436
int10_to_str(i, buff_end+1, 10);
437
if (!check_if_keyname_exists(buff,start,end))
438
return sql_strdup(buff);
440
return (char*) "not_specified"; // Should never happen
444
// prepare_blob_field() cut and pasted directly from sql_table.cc.
445
static bool prepare_blob_field(THD *thd, Create_field *sql_field)
447
DBUG_ENTER("prepare_blob_field");
449
if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
450
!(sql_field->flags & BLOB_FLAG))
452
/* Convert long VARCHAR columns to TEXT or BLOB */
453
char warn_buff[MYSQL_ERRMSG_SIZE];
455
if (sql_field->def || (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
456
MODE_STRICT_ALL_TABLES)))
458
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
459
MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
462
sql_field->sql_type= MYSQL_TYPE_BLOB;
463
sql_field->flags|= BLOB_FLAG;
464
sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
465
(sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
466
(sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
467
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
471
if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
473
if (sql_field->sql_type == MYSQL_TYPE_BLOB)
475
/* The user has given a length to the blob column */
476
sql_field->sql_type= get_blob_type_from_length(sql_field->length);
477
sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
479
sql_field->length= 0;
484
//////////////////////////////
485
// mysql_prepare_create_table() cut and pasted directly from sql_table.cc.
487
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
488
Alter_info *alter_info,
491
handler *file, KEY **key_info_buffer,
492
uint *key_count, int select_field_count)
494
const char *key_name;
495
Create_field *sql_field,*dup_field;
496
uint field,null_fields,blob_columns,max_key_length;
497
ulong record_offset= 0;
499
KEY_PART_INFO *key_part_info;
500
int timestamps= 0, timestamps_with_niladic= 0;
502
int select_field_pos,auto_increment=0;
503
List_iterator<Create_field> it(alter_info->create_list);
504
List_iterator<Create_field> it2(alter_info->create_list);
505
uint total_uneven_bit_length= 0;
506
DBUG_ENTER("mysql_prepare_create_table");
508
select_field_pos= alter_info->create_list.elements - select_field_count;
509
null_fields=blob_columns=0;
510
create_info->varchar= 0;
511
max_key_length= file->max_key_length();
513
for (field_no=0; (sql_field=it++) ; field_no++)
515
CHARSET_INFO *save_cs;
518
Initialize length from its original value (number of characters),
519
which was set in the parser. This is necessary if we're
520
executing a prepared statement for the second time.
522
sql_field->length= sql_field->char_length;
523
if (!sql_field->charset)
524
sql_field->charset= create_info->default_table_charset;
526
table_charset is set in ALTER TABLE if we want change character set
527
for all varchar/char columns.
528
But the table charset must not affect the BLOB fields, so don't
529
allow to change my_charset_bin to somethig else.
531
if (create_info->table_charset && sql_field->charset != &my_charset_bin)
532
sql_field->charset= create_info->table_charset;
534
save_cs= sql_field->charset;
535
if ((sql_field->flags & BINCMP_FLAG) &&
536
!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
537
MY_CS_BINSORT,MYF(0))))
540
strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
541
STRING_WITH_LEN("_bin"));
542
my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
547
Convert the default value from client character
548
set into the column character set if necessary.
550
if (sql_field->def &&
551
save_cs != sql_field->def->collation.collation &&
552
(sql_field->sql_type == MYSQL_TYPE_VAR_STRING ||
553
sql_field->sql_type == MYSQL_TYPE_STRING ||
554
sql_field->sql_type == MYSQL_TYPE_SET ||
555
sql_field->sql_type == MYSQL_TYPE_ENUM))
558
Starting from 5.1 we work here with a copy of Create_field
559
created by the caller, not with the instance that was
560
originally created during parsing. It's OK to create
561
a temporary item and initialize with it a member of the
562
copy -- this item will be thrown away along with the copy
563
at the end of execution, and thus not introduce a dangling
564
pointer in the parsed tree of a prepared statement or a
565
stored procedure statement.
567
sql_field->def= sql_field->def->safe_charset_converter(save_cs);
569
if (sql_field->def == NULL)
571
/* Could not convert */
572
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
577
if (sql_field->sql_type == MYSQL_TYPE_SET ||
578
sql_field->sql_type == MYSQL_TYPE_ENUM)
581
CHARSET_INFO *cs= sql_field->charset;
582
TYPELIB *interval= sql_field->interval;
585
Create typelib from interval_list, and if necessary
586
convert strings from client character set to the
587
column character set.
592
Create the typelib in runtime memory - we will free the
593
occupied memory at the same time when we free this
594
sql_field -- at the end of execution.
596
interval= sql_field->interval= typelib(thd->mem_root,
597
sql_field->interval_list);
598
List_iterator<String> int_it(sql_field->interval_list);
601
int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
604
DBUG_ASSERT(comma_length > 0);
605
for (uint i= 0; (tmp= int_it++); i++)
608
if (String::needs_conversion(tmp->length(), tmp->charset(),
612
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
613
interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
615
interval->type_lengths[i]= conv.length();
618
// Strip trailing spaces.
619
lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
620
interval->type_lengths[i]);
621
interval->type_lengths[i]= lengthsp;
622
((uchar *)interval->type_names[i])[lengthsp]= '\0';
623
if (sql_field->sql_type == MYSQL_TYPE_SET)
625
if (cs->coll->instr(cs, interval->type_names[i],
626
interval->type_lengths[i],
627
comma_buf, comma_length, NULL, 0))
629
my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr());
634
sql_field->interval_list.empty(); // Don't need interval_list anymore
637
if (sql_field->sql_type == MYSQL_TYPE_SET)
640
if (sql_field->def != NULL)
645
String str, *def= sql_field->def->val_str(&str);
646
if (def == NULL) /* SQL "NULL" maps to NULL */
648
if ((sql_field->flags & NOT_NULL_FLAG) != 0)
650
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
654
/* else, NULL is an allowed value */
655
(void) find_set(interval, NULL, 0,
656
cs, ¬_used, ¬_used2, ¬_found);
660
(void) find_set(interval, def->ptr(), def->length(),
661
cs, ¬_used, ¬_used2, ¬_found);
666
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
670
calculate_interval_lengths(cs, interval, &dummy, &field_length);
671
sql_field->length= field_length + (interval->count - 1);
673
else /* MYSQL_TYPE_ENUM */
676
DBUG_ASSERT(sql_field->sql_type == MYSQL_TYPE_ENUM);
677
if (sql_field->def != NULL)
679
String str, *def= sql_field->def->val_str(&str);
680
if (def == NULL) /* SQL "NULL" maps to NULL */
682
if ((sql_field->flags & NOT_NULL_FLAG) != 0)
684
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
688
/* else, the defaults yield the correct length for NULLs. */
692
def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
693
if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
695
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
700
calculate_interval_lengths(cs, interval, &field_length, &dummy);
701
sql_field->length= field_length;
703
set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
706
if (sql_field->sql_type == MYSQL_TYPE_BIT)
708
sql_field->pack_flag= FIELDFLAG_NUMBER;
709
if (file->ha_table_flags() & HA_CAN_BIT_FIELD)
710
total_uneven_bit_length+= sql_field->length & 7;
712
sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
715
sql_field->create_length_to_internal_length();
716
if (prepare_blob_field(thd, sql_field))
719
if (!(sql_field->flags & NOT_NULL_FLAG))
722
if (check_column_name(sql_field->field_name))
724
my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
728
/* Check if we have used the same field name before */
729
for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
731
if (my_strcasecmp(system_charset_info,
732
sql_field->field_name,
733
dup_field->field_name) == 0)
736
If this was a CREATE ... SELECT statement, accept a field
737
redefinition if we are changing a field in the SELECT part
739
if (field_no < select_field_pos || dup_no >= select_field_pos)
741
my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
746
/* Field redefined */
747
sql_field->def= dup_field->def;
748
sql_field->sql_type= dup_field->sql_type;
749
sql_field->charset= (dup_field->charset ?
751
create_info->default_table_charset);
752
sql_field->length= dup_field->char_length;
753
sql_field->pack_length= dup_field->pack_length;
754
sql_field->key_length= dup_field->key_length;
755
sql_field->decimals= dup_field->decimals;
756
sql_field->create_length_to_internal_length();
757
sql_field->unireg_check= dup_field->unireg_check;
759
We're making one field from two, the result field will have
760
dup_field->flags as flags. If we've incremented null_fields
761
because of sql_field->flags, decrement it back.
763
if (!(sql_field->flags & NOT_NULL_FLAG))
765
sql_field->flags= dup_field->flags;
766
sql_field->interval= dup_field->interval;
767
it2.remove(); // Remove first (create) definition
773
/* Don't pack rows in old tables if the user has requested this */
774
if ((sql_field->flags & BLOB_FLAG) ||
775
(sql_field->sql_type == MYSQL_TYPE_VARCHAR &&
776
create_info->row_type != ROW_TYPE_FIXED))
777
(*db_options)|= HA_OPTION_PACK_RECORD;
781
/* record_offset will be increased with 'length-of-null-bits' later */
783
null_fields+= total_uneven_bit_length;
786
while ((sql_field=it++))
788
DBUG_ASSERT(sql_field->charset != 0);
790
if (prepare_create_field(sql_field, &blob_columns,
791
×tamps, ×tamps_with_niladic,
792
file->ha_table_flags()))
794
if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
795
create_info->varchar= TRUE;
796
sql_field->offset= record_offset;
797
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
799
record_offset+= sql_field->pack_length;
801
if (timestamps_with_niladic > 1)
803
my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
804
ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
807
if (auto_increment > 1)
809
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
812
if (auto_increment &&
813
(file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
815
my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
816
ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
820
if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
822
my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
829
List_iterator<Key> key_iterator(alter_info->key_list);
830
List_iterator<Key> key_iterator2(alter_info->key_list);
831
uint key_parts=0, fk_key_count=0;
832
bool primary_key=0,unique_key=0;
834
uint tmp, key_number;
835
/* special marker for keys to be ignored */
836
static char ignore_key[1];
838
/* Calculate number of key segements */
841
while ((key=key_iterator++))
843
DBUG_PRINT("info", ("key name: '%s' type: %d", key->DOT_STR(name) ? key->DOT_STR(name) :
844
"(none)" , key->type));
845
LEX_STRING key_name_str;
846
if (key->type == Key::FOREIGN_KEY)
849
Foreign_key *fk_key= (Foreign_key*) key;
850
if (fk_key->ref_columns.elements &&
851
fk_key->ref_columns.elements != fk_key->columns.elements)
853
my_error(ER_WRONG_FK_DEF, MYF(0),
854
(fk_key->DOT_STR(name) ? fk_key->DOT_STR(name) : "foreign key without name"),
855
ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
861
tmp=file->max_key_parts();
862
if (key->columns.elements > tmp)
864
my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
867
key_name_str.str= (char*) key->DOT_STR(name);
868
key_name_str.length= key->DOT_STR(name) ? strlen(key->DOT_STR(name)) : 0;
869
if (check_string_char_length(&key_name_str, "", NAME_CHAR_LEN,
870
system_charset_info, 1))
872
my_error(ER_TOO_LONG_IDENT, MYF(0), key->DOT_STR(name));
875
key_iterator2.rewind ();
876
if (key->type != Key::FOREIGN_KEY)
878
while ((key2 = key_iterator2++) != key)
881
foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is
882
'generated', and a generated key is a prefix of the other key.
883
Then we do not need the generated shorter key.
885
if ((key2->type != Key::FOREIGN_KEY &&
886
key2->DOT_STR(name) != ignore_key &&
887
!foreign_key_prefix(key, key2)))
889
/* TODO: issue warning message */
890
/* mark that the generated key should be ignored */
891
if (!key2->generated ||
892
(key->generated && key->columns.elements <
893
key2->columns.elements))
894
key->DOT_STR(name)= ignore_key;
897
key2->DOT_STR(name)= ignore_key;
898
key_parts-= key2->columns.elements;
905
if (key->DOT_STR(name) != ignore_key)
906
key_parts+=key->columns.elements;
909
if (key->DOT_STR(name) && !tmp_table && (key->type != Key::PRIMARY) &&
910
!my_strcasecmp(system_charset_info,key->DOT_STR(name),primary_key_name))
912
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->DOT_STR(name));
916
tmp=file->max_keys();
917
if (*key_count > tmp)
919
my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
923
(*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
924
key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
925
if (!*key_info_buffer || ! key_part_info)
926
DBUG_RETURN(TRUE); // Out of memory
928
key_iterator.rewind();
930
for (; (key=key_iterator++) ; key_number++)
933
Key_part_spec *column;
935
if (key->DOT_STR(name) == ignore_key)
937
/* ignore redundant keys */
940
while (key && key->DOT_STR(name) == ignore_key);
950
key_info->flags= HA_FULLTEXT;
951
if ((key_info->parser_name= &key->key_create_info.parser_name)->str)
952
key_info->flags|= HA_USES_PARSER;
954
key_info->parser_name= 0;
958
key_info->flags= HA_SPATIAL;
961
my_error(ER_FEATURE_DISABLED, MYF(0),
962
sym_group_geom.name, sym_group_geom.needed_define);
965
case Key::FOREIGN_KEY:
966
key_number--; // Skip this key
969
key_info->flags = HA_NOSAME;
973
key_info->flags|= HA_GENERATED_KEY;
975
key_info->key_parts=(uint8) key->columns.elements;
976
key_info->key_part=key_part_info;
977
key_info->usable_key_parts= key_number;
978
key_info->algorithm= key->key_create_info.algorithm;
980
if (key->type == Key::FULLTEXT)
982
if (!(file->ha_table_flags() & HA_CAN_FULLTEXT))
984
my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT),
990
Make SPATIAL to be RTREE by default
991
SPATIAL only on BLOB or at least BINARY, this
992
actually should be replaced by special GEOM type
993
in near future when new frm file is ready
994
checking for proper key parts number:
997
/* TODO: Add proper checks if handler supports key_type and algorithm */
998
if (key_info->flags & HA_SPATIAL)
1000
if (!(file->ha_table_flags() & HA_CAN_RTREEKEYS))
1002
my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS),
1006
if (key_info->key_parts != 1)
1008
my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
1012
else if (key_info->algorithm == HA_KEY_ALG_RTREE)
1014
#ifdef HAVE_RTREE_KEYS
1015
if ((key_info->key_parts & 1) == 1)
1017
my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX");
1020
/* TODO: To be deleted */
1021
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX");
1024
my_error(ER_FEATURE_DISABLED, MYF(0),
1025
sym_group_rtree.name, sym_group_rtree.needed_define);
1030
/* Take block size from key part or table part */
1032
TODO: Add warning if block size changes. We can't do it here, as
1033
this may depend on the size of the key
1035
key_info->block_size= (key->key_create_info.block_size ?
1036
key->key_create_info.block_size :
1037
create_info->key_block_size);
1039
if (key_info->block_size)
1040
key_info->flags|= HA_USES_BLOCK_SIZE;
1042
List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
1043
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
1044
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
1047
Key_part_spec *dup_column;
1051
while ((sql_field=it++) &&
1052
my_strcasecmp(system_charset_info,
1053
column->DOT_STR(field_name),
1054
sql_field->field_name))
1058
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
1061
while ((dup_column= cols2++) != column)
1063
if (!my_strcasecmp(system_charset_info,
1064
column->DOT_STR(field_name), dup_column->DOT_STR(field_name)))
1066
my_printf_error(ER_DUP_FIELDNAME,
1067
ER(ER_DUP_FIELDNAME),MYF(0),
1068
column->field_name);
1073
if (key->type == Key::FULLTEXT)
1075
if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
1076
sql_field->sql_type != MYSQL_TYPE_VARCHAR &&
1077
!f_is_blob(sql_field->pack_flag)) ||
1078
sql_field->charset == &my_charset_bin ||
1079
sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
1080
(ft_key_charset && sql_field->charset != ft_key_charset))
1082
my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name);
1085
ft_key_charset=sql_field->charset;
1087
for fulltext keys keyseg length is 1 for blobs (it's ignored in ft
1088
code anyway, and 0 (set to column width later) for char's. it has
1089
to be correct col width for char's, as char data are not prefixed
1090
with length (unlike blobs, where ft code takes data length from a
1091
data prefix, ignoring column->length).
1093
column->length=test(f_is_blob(sql_field->pack_flag));
1097
column->length*= sql_field->charset->mbmaxlen;
1099
if (key->type == Key::SPATIAL && column->length)
1101
my_error(ER_WRONG_SUB_KEY, MYF(0));
1105
if (f_is_blob(sql_field->pack_flag) ||
1106
(f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
1108
if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
1110
my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name);
1113
if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
1116
if (!column->length)
1118
my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name);
1123
if (key->type == Key::SPATIAL)
1125
if (!column->length)
1128
4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
1129
Lately we'll extend this code to support more dimensions
1131
column->length= 4*sizeof(double);
1135
if (!(sql_field->flags & NOT_NULL_FLAG))
1137
if (key->type == Key::PRIMARY)
1139
/* Implicitly set primary key fields to NOT NULL for ISO conf. */
1140
sql_field->flags|= NOT_NULL_FLAG;
1141
sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
1146
key_info->flags|= HA_NULL_PART_KEY;
1147
if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
1149
my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name);
1152
if (key->type == Key::SPATIAL)
1154
my_message(ER_SPATIAL_CANT_HAVE_NULL,
1155
ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
1160
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1162
if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
1163
auto_increment--; // Field is used
1167
key_part_info->fieldnr= field;
1168
key_part_info->offset= (uint16) sql_field->offset;
1169
key_part_info->key_type=sql_field->pack_flag;
1170
length= sql_field->key_length;
1174
if (f_is_blob(sql_field->pack_flag))
1176
if ((length=column->length) > max_key_length ||
1177
length > file->max_key_part_length())
1179
length=min(max_key_length, file->max_key_part_length());
1180
if (key->type == Key::MULTIPLE)
1182
/* not a critical problem */
1183
char warn_buff[MYSQL_ERRMSG_SIZE];
1184
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
1186
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1187
ER_TOO_LONG_KEY, warn_buff);
1188
/* Align key length to multibyte char boundary */
1189
length-= length % sql_field->charset->mbmaxlen;
1193
my_error(ER_TOO_LONG_KEY,MYF(0),length);
1198
else if (!f_is_geom(sql_field->pack_flag) &&
1199
(column->length > length ||
1200
!Field::type_can_have_key_part (sql_field->sql_type) ||
1201
((f_is_packed(sql_field->pack_flag) ||
1202
((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
1203
(key_info->flags & HA_NOSAME))) &&
1204
column->length != length)))
1206
my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1209
else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
1210
length=column->length;
1212
else if (length == 0)
1214
my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name);
1217
if (length > file->max_key_part_length() && key->type != Key::FULLTEXT)
1219
length= file->max_key_part_length();
1220
if (key->type == Key::MULTIPLE)
1222
/* not a critical problem */
1223
char warn_buff[MYSQL_ERRMSG_SIZE];
1224
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
1226
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1227
ER_TOO_LONG_KEY, warn_buff);
1228
/* Align key length to multibyte char boundary */
1229
length-= length % sql_field->charset->mbmaxlen;
1233
my_error(ER_TOO_LONG_KEY,MYF(0),length);
1237
key_part_info->length=(uint16) length;
1238
/* Use packed keys for long strings on the first column */
1239
if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
1240
(length >= KEY_DEFAULT_PACK_LENGTH &&
1241
(sql_field->sql_type == MYSQL_TYPE_STRING ||
1242
sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
1243
sql_field->pack_flag & FIELDFLAG_BLOB)))
1245
if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
1246
sql_field->sql_type == MYSQL_TYPE_VARCHAR)
1247
key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1249
key_info->flags|= HA_PACK_KEY;
1251
/* Check if the key segment is partial, set the key flag accordingly */
1252
if (length != sql_field->key_length)
1253
key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
1258
/* Create the key name based on the first column (if not given) */
1261
if (key->type == Key::PRIMARY)
1265
my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
1269
key_name=primary_key_name;
1272
else if (!(key_name = key->DOT_STR(name)))
1273
key_name=make_unique_key_name(sql_field->field_name,
1274
*key_info_buffer, key_info);
1275
if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
1277
my_error(ER_DUP_KEYNAME, MYF(0), key_name);
1280
key_info->name=(char*) key_name;
1283
if (!key_info->name || check_column_name(key_info->name))
1285
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1288
if (!(key_info->flags & HA_NULL_PART_KEY))
1290
key_info->key_length=(uint16) key_length;
1291
if (key_length > max_key_length && key->type != Key::FULLTEXT)
1293
my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1298
if (!unique_key && !primary_key &&
1299
(file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1301
my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1304
if (auto_increment > 0)
1306
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1309
/* Sort keys in optimized order */
1310
my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
1311
(qsort_cmp) sort_keys);
1312
create_info->null_bits= null_fields;
1316
while ((sql_field=it++))
1318
Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1320
if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
1322
sql_field->sql_type == MYSQL_TYPE_TIMESTAMP &&
1323
(sql_field->flags & NOT_NULL_FLAG) &&
1324
(type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1327
An error should be reported if:
1328
- NO_ZERO_DATE SQL mode is active;
1329
- there is no explicit DEFAULT clause (default column value);
1330
- this is a TIMESTAMP column;
1331
- the column is not NULL;
1332
- this is not the DEFAULT CURRENT_TIMESTAMP column.
1334
In other words, an error should be reported if
1335
- NO_ZERO_DATE SQL mode is active;
1336
- the column definition is equivalent to
1337
'column_name TIMESTAMP DEFAULT 0'.
1340
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
1348
//////////////////////////////
1349
// mysql_create_table_no_lock() cut and pasted directly from sql_table.cc. (I did make is static after copying it.)
1351
static bool mysql_create_table_no_lock(THD *thd,
1352
const char *db, const char *table_name,
1353
HA_CREATE_INFO *create_info,
1354
Alter_info *alter_info,
1355
bool internal_tmp_table,
1356
uint select_field_count)
1358
char path[FN_REFLEN];
1361
uint db_options, key_count;
1362
KEY *key_info_buffer;
1365
DBUG_ENTER("mysql_create_table_no_lock");
1366
DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d",
1367
db, table_name, internal_tmp_table));
1370
/* Check for duplicate fields and check type of table to create */
1371
if (!alter_info->create_list.elements)
1373
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1377
if (check_engine(thd, table_name, create_info))
1379
db_options= create_info->table_options;
1380
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1381
db_options|=HA_OPTION_PACK_RECORD;
1382
alias= table_case_name(create_info, table_name);
1384
/* PMC - Done to avoid getting the partition handler by mistake! */
1385
if (!(file= new (thd->mem_root) ha_xtsys(pbxt_hton, NULL)))
1387
mem_alloc_error(sizeof(handler));
1391
set_table_default_charset(thd, create_info, (char*) db);
1393
if (mysql_prepare_create_table(thd, create_info, alter_info,
1396
&key_info_buffer, &key_count,
1397
select_field_count))
1400
/* Check if table exists */
1401
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1403
path_length= build_tmptable_filename(thd, path, sizeof(path));
1404
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
1409
/* check if the table name contains FN_DEVCHAR when defined */
1410
if (strchr(alias, FN_DEVCHAR))
1412
my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
1416
path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
1417
internal_tmp_table ? FN_IS_TMP : 0);
1420
/* Check if table already exists */
1421
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1422
find_temporary_table(thd, db, table_name))
1424
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1426
create_info->table_existed= 1; // Mark that table existed
1427
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1428
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1433
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
1437
pthread_mutex_lock(&LOCK_open);
1438
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1440
if (!access(path,F_OK))
1442
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1444
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1445
goto unlock_and_end;
1448
We don't assert here, but check the result, because the table could be
1449
in the table definition cache and in the same time the .frm could be
1450
missing from the disk, in case of manual intervention which deletes
1451
the .frm file. The user has to use FLUSH TABLES; to clear the cache.
1452
Then she could create the table. This case is pretty obscure and
1453
therefore we don't introduce a new error message only for it.
1455
if (get_cached_table_share(db, alias))
1457
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1458
goto unlock_and_end;
1463
Check that table with given name does not already
1464
exist in any storage engine. In such a case it should
1465
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1466
unless user specified CREATE TABLE IF EXISTS
1467
The LOCK_open mutex has been locked to make sure no
1468
one else is attempting to discover the table. Since
1469
it's not on disk as a frm file, no one could be using it!
1471
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1473
bool create_if_not_exists =
1474
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
1475
int retcode = ha_table_exists_in_engine(thd, db, table_name);
1476
DBUG_PRINT("info", ("exists_in_engine: %u",retcode));
1479
case HA_ERR_NO_SUCH_TABLE:
1480
/* Normal case, no table exists. we can go and create it */
1482
case HA_ERR_TABLE_EXIST:
1483
DBUG_PRINT("info", ("Table existed in handler"));
1485
if (create_if_not_exists)
1487
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1488
goto unlock_and_end;
1491
DBUG_PRINT("info", ("error: %u from storage engine", retcode));
1492
my_error(retcode, MYF(0),table_name);
1493
goto unlock_and_end;
1497
thd_proc_info(thd, "creating table");
1498
create_info->table_existed= 0; // Mark that table is created
1500
create_info->table_options=db_options;
1502
path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
1503
if (rea_create_table(thd, path, db, table_name,
1504
create_info, alter_info->create_list,
1505
key_count, key_info_buffer, file))
1506
goto unlock_and_end;
1508
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1510
/* Open table and put in temporary table list */
1511
#if MYSQL_VERSION_ID >= 50404
1512
if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
1514
if (!(open_temporary_table(thd, path, db, table_name, 1)))
1517
#if MYSQL_VERSION_ID >= 50404
1518
(void) rm_temporary_table(create_info->db_type, path, false);
1520
(void) rm_temporary_table(create_info->db_type, path);
1522
goto unlock_and_end;
1524
thd->thread_specific_used= TRUE;
1528
Don't write statement if:
1529
- It is an internal temporary table,
1530
- Row-based logging is used and it we are creating a temporary table, or
1531
- The binary log is not open.
1532
Otherwise, the statement shall be binlogged.
1535
* Firstly we had a compile problem with MySQL 5.1.42 and
1536
* the write_bin_log() call below:
1537
* discover_xt.cc:1259: error: argument of type 'char* (Statement::)()' does not match 'const char*'
1539
* And secondly, we should no write the BINLOG anyway because this is
1540
* an internal PBXT system table.
1542
* So I am just commenting out the code altogether.
1543
if (!internal_tmp_table &&
1544
(!thd->current_stmt_binlog_row_based ||
1545
(thd->current_stmt_binlog_row_based &&
1546
!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1547
write_bin_log(thd, TRUE, thd->query, thd->query_length);
1551
pthread_mutex_unlock(&LOCK_open);
1554
thd_proc_info(thd, "After create");
1560
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1561
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1563
create_info->table_existed= 1; // Mark that table existed
1564
goto unlock_and_end;
1567
////////////////////////////////////////////////////////
1568
////// END OF CUT AND PASTES FROM sql_table.cc ////////
1569
////////////////////////////////////////////////////////
1572
#endif // LOCK_OPEN_HACK_REQUIRED
1574
//------------------------------
1575
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)
1578
#define MYLEX_CREATE_INFO create_info
1580
#define MYLEX_CREATE_INFO mylex.create_info
1584
drizzled::statement::AlterTable *stmt = new drizzled::statement::AlterTable(thd);
1585
HA_CREATE_INFO create_info;
1586
//AlterInfo alter_info;
1587
drizzled::message::Table table_proto;
1589
static const char *ext = ".dfe";
1590
static const int ext_len = 4;
1592
table_proto.mutable_engine()->mutable_name()->assign("PBXT");
1594
static const char *ext = ".frm";
1595
static const int ext_len = 4;
1598
char field_length_buffer[12], *field_length_ptr;
1599
LEX *save_lex= thd->lex, mylex;
1601
memset(&MYLEX_CREATE_INFO, 0, sizeof(HA_CREATE_INFO));
1606
mylex.statement = stmt;
1609
/* setup the create info */
1610
MYLEX_CREATE_INFO.db_type = hton;
1613
mylex.create_info.frm_only = 1;
1615
MYLEX_CREATE_INFO.default_table_charset = system_charset_info;
1617
/* setup the column info. */
1618
while (info->field_name) {
1619
LEX_STRING field_name, comment;
1620
field_name.str = (char*)(info->field_name);
1621
field_name.length = strlen(info->field_name);
1623
comment.str = (char*)(info->comment);
1624
comment.length = strlen(info->comment);
1626
if (info->field_length) {
1627
sprintf(field_length_buffer, "%d", info->field_length);
1628
field_length_ptr = field_length_buffer;
1630
field_length_ptr = NULL;
1633
if (add_field_to_list(thd, &field_name, info->field_type, field_length_ptr, info->field_decimal_length,
1635
COLUMN_FORMAT_TYPE_FIXED,
1636
NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
1637
NULL /*interval_list*/, info->field_charset))
1639
if (add_field_to_list(thd, &field_name, info->field_type, field_length_ptr, info->field_decimal_length,
1641
#if MYSQL_VERSION_ID >= 50404
1643
COLUMN_FORMAT_TYPE_FIXED,
1645
NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
1646
NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/))
1654
if (skip_existing) {
1655
size_t db_len = strlen(db);
1656
size_t name_len = strlen(name);
1657
size_t len = db_len + 1 + name_len + ext_len + 1;
1658
char *path = (char *)xt_malloc_ns(len);
1659
memcpy(path, db, db_len);
1660
memcpy(path + db_len + 1, name, name_len);
1661
memcpy(path + db_len + 1 + name_len, ext, ext_len);
1662
path[db_len] = XT_DIR_CHAR;
1663
path[len - 1] = '\0';
1664
xtBool exists = xt_fs_exists(path);
1670
/* Create an internal temp table */
1672
table_proto.set_name(name);
1673
table_proto.set_type(drizzled::message::Table::STANDARD);
1674
table_proto.set_schema(db);
1675
table_proto.set_creation_timestamp(time(NULL));
1676
table_proto.set_update_timestamp(time(NULL));
1677
if (mysql_create_table_no_lock(thd, db, name, &create_info, &table_proto, &stmt->alter_info, 1, 0, skip_existing))
1680
if (mysql_create_table_no_lock(thd, db, name, &mylex.create_info, &mylex.alter_info, 1, 0))
1689
thd->lex = save_lex;