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 "item_create.h"
30
#include "sql_table.h"
31
#include "sql_class.h"
33
#include "sql_parse.h"
35
#include "sql_partition.h" // mem_alloc_error()
37
#include <drizzled/session.h>
38
#include <drizzled/server_includes.h>
39
#include <drizzled/sql_base.h>
40
#include <drizzled/statement/alter_table.h>
45
#include "strutil_xt.h"
47
#include "discover_xt.h"
51
#if MYSQL_VERSION_ID >= 50404
52
#define DOT_STR(x) x.str
59
#define LOCK_OPEN_HACK_REQUIRED
62
#ifdef LOCK_OPEN_HACK_REQUIRED
65
using namespace drizzled;
68
#define mysql_create_table_no_lock hacked_mysql_create_table_no_lock
72
int rea_create_table(Session *session, const char *path,
73
const char *db, const char *table_name,
74
message::Table *table_proto,
75
HA_CREATE_INFO *create_info,
76
List<CreateField> &create_field,
77
uint32_t key_count,KEY *key_info);
80
static uint32_t build_tmptable_filename(Session* session,
81
char *buff, size_t bufflen)
84
ostringstream path_str, post_tmpdir_str;
87
path_str << drizzle_tmpdir;
88
post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
89
post_tmpdir_str << session->thread_id << session->tmp_table++;
90
tmp= post_tmpdir_str.str();
92
transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
96
if (bufflen < path_str.str().length())
99
length= unpack_filename(buff, path_str.str().c_str());
104
static bool mysql_create_table_no_lock(Session *session,
105
const char *db, const char *table_name,
106
HA_CREATE_INFO *create_info,
107
message::Table *table_proto,
108
AlterInfo *alter_info,
109
bool internal_tmp_table,
110
uint32_t select_field_count)
112
char path[FN_REFLEN];
113
uint32_t path_length;
114
uint db_options, key_count;
115
KEY *key_info_buffer;
118
/* Check for duplicate fields and check type of table to create */
119
if (!alter_info->create_list.elements)
121
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
125
assert(strcmp(table_name,table_proto->name().c_str())==0);
126
if (check_engine(session, table_name, create_info))
128
db_options= create_info->table_options;
129
if (create_info->row_type == ROW_TYPE_DYNAMIC)
130
db_options|=HA_OPTION_PACK_RECORD;
132
/*if (!(file= create_info->db_type->getCursor((TableShare*) 0, session->mem_root)))
134
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
138
/* PMC - Done to avoid getting the partition handler by mistake! */
139
if (!(file= new (session->mem_root) ha_xtsys(pbxt_hton, NULL)))
141
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
145
set_table_default_charset(create_info, (char*) db);
147
if (mysql_prepare_create_table(session,
153
&key_info_buffer, &key_count,
157
/* Check if table exists */
158
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
160
path_length= build_tmptable_filename(session, path, sizeof(path));
165
/* check if the table name contains FN_DEVCHAR when defined */
166
if (strchr(table_name, FN_DEVCHAR))
168
my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name);
172
path_length= build_table_filename(path, sizeof(path), db, table_name, internal_tmp_table);
175
/* Check if table already exists */
176
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
177
session->find_temporary_table(db, table_name))
179
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
181
create_info->table_existed= 1; // Mark that table existed
182
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
183
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
188
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
192
//pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
193
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
195
if (plugin::StorageEngine::getTableDefinition(*session,
199
internal_tmp_table) == EEXIST)
201
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
204
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
205
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
207
create_info->table_existed= 1; // Mark that table existed
210
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
215
* We don't assert here, but check the result, because the table could be
216
* in the table definition cache and in the same time the .frm could be
217
* missing from the disk, in case of manual intervention which deletes
218
* the .frm file. The user has to use FLUSH TABLES; to clear the cache.
219
* Then she could create the table. This case is pretty obscure and
220
* therefore we don't introduce a new error message only for it.
222
if (TableShare::getShare(db, table_name))
224
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
229
* Check that table with given name does not already
230
* exist in any storage engine. In such a case it should
231
* be discovered and the error ER_TABLE_EXISTS_ERROR be returned
232
* unless user specified CREATE TABLE IF EXISTS
233
* The LOCK_open mutex has been locked to make sure no
234
* one else is attempting to discover the table. Since
235
* it's not on disk as a frm file, no one could be using it!
237
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
239
bool create_if_not_exists =
240
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
242
char table_path[FN_REFLEN];
243
uint32_t table_path_length;
245
table_path_length= build_table_filename(table_path, sizeof(table_path),
246
db, table_name, false);
248
int retcode= plugin::StorageEngine::getTableDefinition(*session,
256
/* Normal case, no table exists. we can go and create it */
259
if (create_if_not_exists)
262
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
263
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
265
create_info->table_existed= 1; // Mark that table existed
268
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
271
my_error(retcode, MYF(0),table_name);
276
session->set_proc_info("creating table");
277
create_info->table_existed= 0; // Mark that table is created
279
create_info->table_options=db_options;
281
if (rea_create_table(session, path, db, table_name,
283
create_info, alter_info->create_list,
284
key_count, key_info_buffer))
287
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
289
/* Open table and put in temporary table list */
290
if (!(session->open_temporary_table(path, db, table_name, 1, OTM_OPEN)))
292
(void) session->rm_temporary_table(create_info->db_type, path);
298
* Don't write statement if:
299
* - It is an internal temporary table,
300
* - Row-based logging is used and it we are creating a temporary table, or
301
* - The binary log is not open.
302
* Otherwise, the statement shall be binlogged.
304
if (!internal_tmp_table &&
305
((!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
306
write_bin_log(session, session->query, session->query_length);
309
//pthread_mutex_unlock(&LOCK_open);
312
session->set_proc_info("After create");
318
///////////////////////////////
320
* Unfortunately I cannot use the standard mysql_create_table_no_lock() because it will lock "LOCK_open"
321
* which has already been locked while the server is performing table discovery. So I have added this hack
322
* in here to create my own version. The following macros will make the changes I need to get it to work.
323
* The actual function code has been copied here without changes.
325
* Its almost enough to make you want to cry. :(
327
//-----------------------------
329
#ifdef pthread_mutex_lock
330
#undef pthread_mutex_lock
333
#ifdef pthread_mutex_unlock
334
#undef pthread_mutex_unlock
337
#define mysql_create_table_no_lock hacked_mysql_create_table_no_lock
338
#define pthread_mutex_lock(l)
339
#define pthread_mutex_unlock(l)
341
#define check_engine(t, n, c) (0)
342
#define set_table_default_charset(t, c, d)
344
void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
345
uint32 *max_length, uint32 *tot_length);
347
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen);
348
uint build_table_filename(char *buff, size_t bufflen, const char *db,
349
const char *table_name, const char *ext, uint flags);
351
//////////////////////////////////////////////////////////
352
////// START OF CUT AND PASTES FROM sql_table.cc ////////
353
//////////////////////////////////////////////////////////
355
// sort_keys() cut and pasted directly from sql_table.cc.
356
static int sort_keys(KEY *a, KEY *b)
358
ulong a_flags= a->flags, b_flags= b->flags;
360
if (a_flags & HA_NOSAME)
362
if (!(b_flags & HA_NOSAME))
364
if ((a_flags ^ b_flags) & HA_NULL_PART_KEY)
366
/* Sort NOT NULL keys before other keys */
367
return (a_flags & HA_NULL_PART_KEY) ? 1 : -1;
369
if (a->name == primary_key_name)
371
if (b->name == primary_key_name)
373
/* Sort keys don't containing partial segments before others */
374
if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
375
return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1;
377
else if (b_flags & HA_NOSAME)
378
return 1; // Prefer b
380
if ((a_flags ^ b_flags) & HA_FULLTEXT)
382
return (a_flags & HA_FULLTEXT) ? 1 : -1;
385
Prefer original key order. usable_key_parts contains here
386
the original key position.
388
return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
389
(a->usable_key_parts > b->usable_key_parts) ? 1 :
393
// check_if_keyname_exists() cut and pasted directly from sql_table.cc.
395
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
397
for (KEY *key=start ; key != end ; key++)
398
if (!my_strcasecmp(system_charset_info,name,key->name))
403
// make_unique_key_name() cut and pasted directly from sql_table.cc.
405
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
407
char buff[MAX_FIELD_NAME],*buff_end;
409
if (!check_if_keyname_exists(field_name,start,end) &&
410
my_strcasecmp(system_charset_info,field_name,primary_key_name))
411
return (char*) field_name; // Use fieldname
412
buff_end=strmake(buff,field_name, sizeof(buff)-4);
415
Only 3 chars + '\0' left, so need to limit to 2 digit
416
This is ok as we can't have more than 100 keys anyway
418
for (uint i=2 ; i< 100; i++)
421
int10_to_str(i, buff_end+1, 10);
422
if (!check_if_keyname_exists(buff,start,end))
423
return sql_strdup(buff);
425
return (char*) "not_specified"; // Should never happen
429
// prepare_blob_field() cut and pasted directly from sql_table.cc.
430
static bool prepare_blob_field(THD *thd, Create_field *sql_field)
432
DBUG_ENTER("prepare_blob_field");
434
if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
435
!(sql_field->flags & BLOB_FLAG))
437
/* Convert long VARCHAR columns to TEXT or BLOB */
438
char warn_buff[MYSQL_ERRMSG_SIZE];
440
if (sql_field->def || (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
441
MODE_STRICT_ALL_TABLES)))
443
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
444
MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
447
sql_field->sql_type= MYSQL_TYPE_BLOB;
448
sql_field->flags|= BLOB_FLAG;
449
sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
450
(sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
451
(sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
452
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
456
if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
458
if (sql_field->sql_type == MYSQL_TYPE_BLOB)
460
/* The user has given a length to the blob column */
461
sql_field->sql_type= get_blob_type_from_length(sql_field->length);
462
sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
464
sql_field->length= 0;
469
//////////////////////////////
470
// mysql_prepare_create_table() cut and pasted directly from sql_table.cc.
472
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
473
Alter_info *alter_info,
476
handler *file, KEY **key_info_buffer,
477
uint *key_count, int select_field_count)
479
const char *key_name;
480
Create_field *sql_field,*dup_field;
481
uint field,null_fields,blob_columns,max_key_length;
482
ulong record_offset= 0;
484
KEY_PART_INFO *key_part_info;
485
int timestamps= 0, timestamps_with_niladic= 0;
487
int select_field_pos,auto_increment=0;
488
List_iterator<Create_field> it(alter_info->create_list);
489
List_iterator<Create_field> it2(alter_info->create_list);
490
uint total_uneven_bit_length= 0;
491
DBUG_ENTER("mysql_prepare_create_table");
493
select_field_pos= alter_info->create_list.elements - select_field_count;
494
null_fields=blob_columns=0;
495
create_info->varchar= 0;
496
max_key_length= file->max_key_length();
498
for (field_no=0; (sql_field=it++) ; field_no++)
500
CHARSET_INFO *save_cs;
503
Initialize length from its original value (number of characters),
504
which was set in the parser. This is necessary if we're
505
executing a prepared statement for the second time.
507
sql_field->length= sql_field->char_length;
508
if (!sql_field->charset)
509
sql_field->charset= create_info->default_table_charset;
511
table_charset is set in ALTER TABLE if we want change character set
512
for all varchar/char columns.
513
But the table charset must not affect the BLOB fields, so don't
514
allow to change my_charset_bin to somethig else.
516
if (create_info->table_charset && sql_field->charset != &my_charset_bin)
517
sql_field->charset= create_info->table_charset;
519
save_cs= sql_field->charset;
520
if ((sql_field->flags & BINCMP_FLAG) &&
521
!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
522
MY_CS_BINSORT,MYF(0))))
525
strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
526
STRING_WITH_LEN("_bin"));
527
my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
532
Convert the default value from client character
533
set into the column character set if necessary.
535
if (sql_field->def &&
536
save_cs != sql_field->def->collation.collation &&
537
(sql_field->sql_type == MYSQL_TYPE_VAR_STRING ||
538
sql_field->sql_type == MYSQL_TYPE_STRING ||
539
sql_field->sql_type == MYSQL_TYPE_SET ||
540
sql_field->sql_type == MYSQL_TYPE_ENUM))
543
Starting from 5.1 we work here with a copy of Create_field
544
created by the caller, not with the instance that was
545
originally created during parsing. It's OK to create
546
a temporary item and initialize with it a member of the
547
copy -- this item will be thrown away along with the copy
548
at the end of execution, and thus not introduce a dangling
549
pointer in the parsed tree of a prepared statement or a
550
stored procedure statement.
552
sql_field->def= sql_field->def->safe_charset_converter(save_cs);
554
if (sql_field->def == NULL)
556
/* Could not convert */
557
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
562
if (sql_field->sql_type == MYSQL_TYPE_SET ||
563
sql_field->sql_type == MYSQL_TYPE_ENUM)
566
CHARSET_INFO *cs= sql_field->charset;
567
TYPELIB *interval= sql_field->interval;
570
Create typelib from interval_list, and if necessary
571
convert strings from client character set to the
572
column character set.
577
Create the typelib in runtime memory - we will free the
578
occupied memory at the same time when we free this
579
sql_field -- at the end of execution.
581
interval= sql_field->interval= typelib(thd->mem_root,
582
sql_field->interval_list);
583
List_iterator<String> int_it(sql_field->interval_list);
586
int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
589
DBUG_ASSERT(comma_length > 0);
590
for (uint i= 0; (tmp= int_it++); i++)
593
if (String::needs_conversion(tmp->length(), tmp->charset(),
597
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
598
interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
600
interval->type_lengths[i]= conv.length();
603
// Strip trailing spaces.
604
lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
605
interval->type_lengths[i]);
606
interval->type_lengths[i]= lengthsp;
607
((uchar *)interval->type_names[i])[lengthsp]= '\0';
608
if (sql_field->sql_type == MYSQL_TYPE_SET)
610
if (cs->coll->instr(cs, interval->type_names[i],
611
interval->type_lengths[i],
612
comma_buf, comma_length, NULL, 0))
614
my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr());
619
sql_field->interval_list.empty(); // Don't need interval_list anymore
622
if (sql_field->sql_type == MYSQL_TYPE_SET)
625
if (sql_field->def != NULL)
630
String str, *def= sql_field->def->val_str(&str);
631
if (def == NULL) /* SQL "NULL" maps to NULL */
633
if ((sql_field->flags & NOT_NULL_FLAG) != 0)
635
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
639
/* else, NULL is an allowed value */
640
(void) find_set(interval, NULL, 0,
641
cs, ¬_used, ¬_used2, ¬_found);
645
(void) find_set(interval, def->ptr(), def->length(),
646
cs, ¬_used, ¬_used2, ¬_found);
651
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
655
calculate_interval_lengths(cs, interval, &dummy, &field_length);
656
sql_field->length= field_length + (interval->count - 1);
658
else /* MYSQL_TYPE_ENUM */
661
DBUG_ASSERT(sql_field->sql_type == MYSQL_TYPE_ENUM);
662
if (sql_field->def != NULL)
664
String str, *def= sql_field->def->val_str(&str);
665
if (def == NULL) /* SQL "NULL" maps to NULL */
667
if ((sql_field->flags & NOT_NULL_FLAG) != 0)
669
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
673
/* else, the defaults yield the correct length for NULLs. */
677
def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
678
if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
680
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
685
calculate_interval_lengths(cs, interval, &field_length, &dummy);
686
sql_field->length= field_length;
688
set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
691
if (sql_field->sql_type == MYSQL_TYPE_BIT)
693
sql_field->pack_flag= FIELDFLAG_NUMBER;
694
if (file->ha_table_flags() & HA_CAN_BIT_FIELD)
695
total_uneven_bit_length+= sql_field->length & 7;
697
sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
700
sql_field->create_length_to_internal_length();
701
if (prepare_blob_field(thd, sql_field))
704
if (!(sql_field->flags & NOT_NULL_FLAG))
707
if (check_column_name(sql_field->field_name))
709
my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
713
/* Check if we have used the same field name before */
714
for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
716
if (my_strcasecmp(system_charset_info,
717
sql_field->field_name,
718
dup_field->field_name) == 0)
721
If this was a CREATE ... SELECT statement, accept a field
722
redefinition if we are changing a field in the SELECT part
724
if (field_no < select_field_pos || dup_no >= select_field_pos)
726
my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
731
/* Field redefined */
732
sql_field->def= dup_field->def;
733
sql_field->sql_type= dup_field->sql_type;
734
sql_field->charset= (dup_field->charset ?
736
create_info->default_table_charset);
737
sql_field->length= dup_field->char_length;
738
sql_field->pack_length= dup_field->pack_length;
739
sql_field->key_length= dup_field->key_length;
740
sql_field->decimals= dup_field->decimals;
741
sql_field->create_length_to_internal_length();
742
sql_field->unireg_check= dup_field->unireg_check;
744
We're making one field from two, the result field will have
745
dup_field->flags as flags. If we've incremented null_fields
746
because of sql_field->flags, decrement it back.
748
if (!(sql_field->flags & NOT_NULL_FLAG))
750
sql_field->flags= dup_field->flags;
751
sql_field->interval= dup_field->interval;
752
it2.remove(); // Remove first (create) definition
758
/* Don't pack rows in old tables if the user has requested this */
759
if ((sql_field->flags & BLOB_FLAG) ||
760
(sql_field->sql_type == MYSQL_TYPE_VARCHAR &&
761
create_info->row_type != ROW_TYPE_FIXED))
762
(*db_options)|= HA_OPTION_PACK_RECORD;
766
/* record_offset will be increased with 'length-of-null-bits' later */
768
null_fields+= total_uneven_bit_length;
771
while ((sql_field=it++))
773
DBUG_ASSERT(sql_field->charset != 0);
775
if (prepare_create_field(sql_field, &blob_columns,
776
×tamps, ×tamps_with_niladic,
777
file->ha_table_flags()))
779
if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
780
create_info->varchar= TRUE;
781
sql_field->offset= record_offset;
782
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
784
record_offset+= sql_field->pack_length;
786
if (timestamps_with_niladic > 1)
788
my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
789
ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
792
if (auto_increment > 1)
794
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
797
if (auto_increment &&
798
(file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
800
my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
801
ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
805
if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
807
my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
814
List_iterator<Key> key_iterator(alter_info->key_list);
815
List_iterator<Key> key_iterator2(alter_info->key_list);
816
uint key_parts=0, fk_key_count=0;
817
bool primary_key=0,unique_key=0;
819
uint tmp, key_number;
820
/* special marker for keys to be ignored */
821
static char ignore_key[1];
823
/* Calculate number of key segements */
826
while ((key=key_iterator++))
828
DBUG_PRINT("info", ("key name: '%s' type: %d", key->DOT_STR(name) ? key->DOT_STR(name) :
829
"(none)" , key->type));
830
LEX_STRING key_name_str;
831
if (key->type == Key::FOREIGN_KEY)
834
Foreign_key *fk_key= (Foreign_key*) key;
835
if (fk_key->ref_columns.elements &&
836
fk_key->ref_columns.elements != fk_key->columns.elements)
838
my_error(ER_WRONG_FK_DEF, MYF(0),
839
(fk_key->DOT_STR(name) ? fk_key->DOT_STR(name) : "foreign key without name"),
840
ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
846
tmp=file->max_key_parts();
847
if (key->columns.elements > tmp)
849
my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
852
key_name_str.str= (char*) key->DOT_STR(name);
853
key_name_str.length= key->DOT_STR(name) ? strlen(key->DOT_STR(name)) : 0;
854
if (check_string_char_length(&key_name_str, "", NAME_CHAR_LEN,
855
system_charset_info, 1))
857
my_error(ER_TOO_LONG_IDENT, MYF(0), key->DOT_STR(name));
860
key_iterator2.rewind ();
861
if (key->type != Key::FOREIGN_KEY)
863
while ((key2 = key_iterator2++) != key)
866
foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is
867
'generated', and a generated key is a prefix of the other key.
868
Then we do not need the generated shorter key.
870
if ((key2->type != Key::FOREIGN_KEY &&
871
key2->DOT_STR(name) != ignore_key &&
872
!foreign_key_prefix(key, key2)))
874
/* TODO: issue warning message */
875
/* mark that the generated key should be ignored */
876
if (!key2->generated ||
877
(key->generated && key->columns.elements <
878
key2->columns.elements))
879
key->DOT_STR(name)= ignore_key;
882
key2->DOT_STR(name)= ignore_key;
883
key_parts-= key2->columns.elements;
890
if (key->DOT_STR(name) != ignore_key)
891
key_parts+=key->columns.elements;
894
if (key->DOT_STR(name) && !tmp_table && (key->type != Key::PRIMARY) &&
895
!my_strcasecmp(system_charset_info,key->DOT_STR(name),primary_key_name))
897
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->DOT_STR(name));
901
tmp=file->max_keys();
902
if (*key_count > tmp)
904
my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
908
(*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
909
key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
910
if (!*key_info_buffer || ! key_part_info)
911
DBUG_RETURN(TRUE); // Out of memory
913
key_iterator.rewind();
915
for (; (key=key_iterator++) ; key_number++)
918
Key_part_spec *column;
920
if (key->DOT_STR(name) == ignore_key)
922
/* ignore redundant keys */
925
while (key && key->DOT_STR(name) == ignore_key);
935
key_info->flags= HA_FULLTEXT;
936
if ((key_info->parser_name= &key->key_create_info.parser_name)->str)
937
key_info->flags|= HA_USES_PARSER;
939
key_info->parser_name= 0;
943
key_info->flags= HA_SPATIAL;
946
my_error(ER_FEATURE_DISABLED, MYF(0),
947
sym_group_geom.name, sym_group_geom.needed_define);
950
case Key::FOREIGN_KEY:
951
key_number--; // Skip this key
954
key_info->flags = HA_NOSAME;
958
key_info->flags|= HA_GENERATED_KEY;
960
key_info->key_parts=(uint8) key->columns.elements;
961
key_info->key_part=key_part_info;
962
key_info->usable_key_parts= key_number;
963
key_info->algorithm= key->key_create_info.algorithm;
965
if (key->type == Key::FULLTEXT)
967
if (!(file->ha_table_flags() & HA_CAN_FULLTEXT))
969
my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT),
975
Make SPATIAL to be RTREE by default
976
SPATIAL only on BLOB or at least BINARY, this
977
actually should be replaced by special GEOM type
978
in near future when new frm file is ready
979
checking for proper key parts number:
982
/* TODO: Add proper checks if handler supports key_type and algorithm */
983
if (key_info->flags & HA_SPATIAL)
985
if (!(file->ha_table_flags() & HA_CAN_RTREEKEYS))
987
my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS),
991
if (key_info->key_parts != 1)
993
my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
997
else if (key_info->algorithm == HA_KEY_ALG_RTREE)
999
#ifdef HAVE_RTREE_KEYS
1000
if ((key_info->key_parts & 1) == 1)
1002
my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX");
1005
/* TODO: To be deleted */
1006
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX");
1009
my_error(ER_FEATURE_DISABLED, MYF(0),
1010
sym_group_rtree.name, sym_group_rtree.needed_define);
1015
/* Take block size from key part or table part */
1017
TODO: Add warning if block size changes. We can't do it here, as
1018
this may depend on the size of the key
1020
key_info->block_size= (key->key_create_info.block_size ?
1021
key->key_create_info.block_size :
1022
create_info->key_block_size);
1024
if (key_info->block_size)
1025
key_info->flags|= HA_USES_BLOCK_SIZE;
1027
List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
1028
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
1029
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
1032
Key_part_spec *dup_column;
1036
while ((sql_field=it++) &&
1037
my_strcasecmp(system_charset_info,
1038
column->DOT_STR(field_name),
1039
sql_field->field_name))
1043
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
1046
while ((dup_column= cols2++) != column)
1048
if (!my_strcasecmp(system_charset_info,
1049
column->DOT_STR(field_name), dup_column->DOT_STR(field_name)))
1051
my_printf_error(ER_DUP_FIELDNAME,
1052
ER(ER_DUP_FIELDNAME),MYF(0),
1053
column->field_name);
1058
if (key->type == Key::FULLTEXT)
1060
if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
1061
sql_field->sql_type != MYSQL_TYPE_VARCHAR &&
1062
!f_is_blob(sql_field->pack_flag)) ||
1063
sql_field->charset == &my_charset_bin ||
1064
sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
1065
(ft_key_charset && sql_field->charset != ft_key_charset))
1067
my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name);
1070
ft_key_charset=sql_field->charset;
1072
for fulltext keys keyseg length is 1 for blobs (it's ignored in ft
1073
code anyway, and 0 (set to column width later) for char's. it has
1074
to be correct col width for char's, as char data are not prefixed
1075
with length (unlike blobs, where ft code takes data length from a
1076
data prefix, ignoring column->length).
1078
column->length=test(f_is_blob(sql_field->pack_flag));
1082
column->length*= sql_field->charset->mbmaxlen;
1084
if (key->type == Key::SPATIAL && column->length)
1086
my_error(ER_WRONG_SUB_KEY, MYF(0));
1090
if (f_is_blob(sql_field->pack_flag) ||
1091
(f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
1093
if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
1095
my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name);
1098
if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
1101
if (!column->length)
1103
my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name);
1108
if (key->type == Key::SPATIAL)
1110
if (!column->length)
1113
4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
1114
Lately we'll extend this code to support more dimensions
1116
column->length= 4*sizeof(double);
1120
if (!(sql_field->flags & NOT_NULL_FLAG))
1122
if (key->type == Key::PRIMARY)
1124
/* Implicitly set primary key fields to NOT NULL for ISO conf. */
1125
sql_field->flags|= NOT_NULL_FLAG;
1126
sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
1131
key_info->flags|= HA_NULL_PART_KEY;
1132
if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
1134
my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name);
1137
if (key->type == Key::SPATIAL)
1139
my_message(ER_SPATIAL_CANT_HAVE_NULL,
1140
ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
1145
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1147
if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
1148
auto_increment--; // Field is used
1152
key_part_info->fieldnr= field;
1153
key_part_info->offset= (uint16) sql_field->offset;
1154
key_part_info->key_type=sql_field->pack_flag;
1155
length= sql_field->key_length;
1159
if (f_is_blob(sql_field->pack_flag))
1161
if ((length=column->length) > max_key_length ||
1162
length > file->max_key_part_length())
1164
length=min(max_key_length, file->max_key_part_length());
1165
if (key->type == Key::MULTIPLE)
1167
/* not a critical problem */
1168
char warn_buff[MYSQL_ERRMSG_SIZE];
1169
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
1171
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1172
ER_TOO_LONG_KEY, warn_buff);
1173
/* Align key length to multibyte char boundary */
1174
length-= length % sql_field->charset->mbmaxlen;
1178
my_error(ER_TOO_LONG_KEY,MYF(0),length);
1183
else if (!f_is_geom(sql_field->pack_flag) &&
1184
(column->length > length ||
1185
!Field::type_can_have_key_part (sql_field->sql_type) ||
1186
((f_is_packed(sql_field->pack_flag) ||
1187
((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
1188
(key_info->flags & HA_NOSAME))) &&
1189
column->length != length)))
1191
my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1194
else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
1195
length=column->length;
1197
else if (length == 0)
1199
my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name);
1202
if (length > file->max_key_part_length() && key->type != Key::FULLTEXT)
1204
length= file->max_key_part_length();
1205
if (key->type == Key::MULTIPLE)
1207
/* not a critical problem */
1208
char warn_buff[MYSQL_ERRMSG_SIZE];
1209
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
1211
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1212
ER_TOO_LONG_KEY, warn_buff);
1213
/* Align key length to multibyte char boundary */
1214
length-= length % sql_field->charset->mbmaxlen;
1218
my_error(ER_TOO_LONG_KEY,MYF(0),length);
1222
key_part_info->length=(uint16) length;
1223
/* Use packed keys for long strings on the first column */
1224
if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
1225
(length >= KEY_DEFAULT_PACK_LENGTH &&
1226
(sql_field->sql_type == MYSQL_TYPE_STRING ||
1227
sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
1228
sql_field->pack_flag & FIELDFLAG_BLOB)))
1230
if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
1231
sql_field->sql_type == MYSQL_TYPE_VARCHAR)
1232
key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1234
key_info->flags|= HA_PACK_KEY;
1236
/* Check if the key segment is partial, set the key flag accordingly */
1237
if (length != sql_field->key_length)
1238
key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
1243
/* Create the key name based on the first column (if not given) */
1246
if (key->type == Key::PRIMARY)
1250
my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
1254
key_name=primary_key_name;
1257
else if (!(key_name = key->DOT_STR(name)))
1258
key_name=make_unique_key_name(sql_field->field_name,
1259
*key_info_buffer, key_info);
1260
if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
1262
my_error(ER_DUP_KEYNAME, MYF(0), key_name);
1265
key_info->name=(char*) key_name;
1268
if (!key_info->name || check_column_name(key_info->name))
1270
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1273
if (!(key_info->flags & HA_NULL_PART_KEY))
1275
key_info->key_length=(uint16) key_length;
1276
if (key_length > max_key_length && key->type != Key::FULLTEXT)
1278
my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1283
if (!unique_key && !primary_key &&
1284
(file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1286
my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1289
if (auto_increment > 0)
1291
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1294
/* Sort keys in optimized order */
1295
my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
1296
(qsort_cmp) sort_keys);
1297
create_info->null_bits= null_fields;
1301
while ((sql_field=it++))
1303
Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1305
if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
1307
sql_field->sql_type == MYSQL_TYPE_TIMESTAMP &&
1308
(sql_field->flags & NOT_NULL_FLAG) &&
1309
(type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1312
An error should be reported if:
1313
- NO_ZERO_DATE SQL mode is active;
1314
- there is no explicit DEFAULT clause (default column value);
1315
- this is a TIMESTAMP column;
1316
- the column is not NULL;
1317
- this is not the DEFAULT CURRENT_TIMESTAMP column.
1319
In other words, an error should be reported if
1320
- NO_ZERO_DATE SQL mode is active;
1321
- the column definition is equivalent to
1322
'column_name TIMESTAMP DEFAULT 0'.
1325
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
1333
//////////////////////////////
1334
// mysql_create_table_no_lock() cut and pasted directly from sql_table.cc. (I did make is static after copying it.)
1336
static bool mysql_create_table_no_lock(THD *thd,
1337
const char *db, const char *table_name,
1338
HA_CREATE_INFO *create_info,
1339
Alter_info *alter_info,
1340
bool internal_tmp_table,
1341
uint select_field_count)
1343
char path[FN_REFLEN];
1346
uint db_options, key_count;
1347
KEY *key_info_buffer;
1350
DBUG_ENTER("mysql_create_table_no_lock");
1351
DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d",
1352
db, table_name, internal_tmp_table));
1355
/* Check for duplicate fields and check type of table to create */
1356
if (!alter_info->create_list.elements)
1358
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1362
if (check_engine(thd, table_name, create_info))
1364
db_options= create_info->table_options;
1365
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1366
db_options|=HA_OPTION_PACK_RECORD;
1367
alias= table_case_name(create_info, table_name);
1369
/* PMC - Done to avoid getting the partition handler by mistake! */
1370
if (!(file= new (thd->mem_root) ha_xtsys(pbxt_hton, NULL)))
1372
mem_alloc_error(sizeof(handler));
1376
set_table_default_charset(thd, create_info, (char*) db);
1378
if (mysql_prepare_create_table(thd, create_info, alter_info,
1381
&key_info_buffer, &key_count,
1382
select_field_count))
1385
/* Check if table exists */
1386
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1388
path_length= build_tmptable_filename(thd, path, sizeof(path));
1389
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
1394
/* check if the table name contains FN_DEVCHAR when defined */
1395
if (strchr(alias, FN_DEVCHAR))
1397
my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
1401
path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
1402
internal_tmp_table ? FN_IS_TMP : 0);
1405
/* Check if table already exists */
1406
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1407
find_temporary_table(thd, db, table_name))
1409
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1411
//create_info->table_existed= 1; // Mark that table existed
1412
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1413
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1418
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
1422
pthread_mutex_lock(&LOCK_open);
1423
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1425
if (!access(path,F_OK))
1427
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1429
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1430
goto unlock_and_end;
1433
We don't assert here, but check the result, because the table could be
1434
in the table definition cache and in the same time the .frm could be
1435
missing from the disk, in case of manual intervention which deletes
1436
the .frm file. The user has to use FLUSH TABLES; to clear the cache.
1437
Then she could create the table. This case is pretty obscure and
1438
therefore we don't introduce a new error message only for it.
1440
if (get_cached_table_share(db, alias))
1442
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1443
goto unlock_and_end;
1448
Check that table with given name does not already
1449
exist in any storage engine. In such a case it should
1450
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1451
unless user specified CREATE TABLE IF EXISTS
1452
The LOCK_open mutex has been locked to make sure no
1453
one else is attempting to discover the table. Since
1454
it's not on disk as a frm file, no one could be using it!
1456
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1458
bool create_if_not_exists =
1459
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
1460
int retcode = ha_table_exists_in_engine(thd, db, table_name);
1461
DBUG_PRINT("info", ("exists_in_engine: %u",retcode));
1464
case HA_ERR_NO_SUCH_TABLE:
1465
/* Normal case, no table exists. we can go and create it */
1467
case HA_ERR_TABLE_EXIST:
1468
DBUG_PRINT("info", ("Table existed in handler"));
1470
if (create_if_not_exists)
1472
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1473
goto unlock_and_end;
1476
DBUG_PRINT("info", ("error: %u from storage engine", retcode));
1477
my_error(retcode, MYF(0),table_name);
1478
goto unlock_and_end;
1482
thd_proc_info(thd, "creating table");
1483
//create_info->table_existed= 0; // Mark that table is created
1485
create_info->table_options=db_options;
1487
path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
1488
if (rea_create_table(thd, path, db, table_name,
1489
create_info, alter_info->create_list,
1490
key_count, key_info_buffer, file))
1491
goto unlock_and_end;
1493
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1495
/* Open table and put in temporary table list */
1496
TABLE *table= open_table_uncached(thd, path, db, table_name, TRUE);
1499
(void) rm_temporary_table(create_info->db_type, path);
1500
goto unlock_and_end;
1502
thd->thread_specific_used= TRUE;
1506
Don't write statement if:
1507
- It is an internal temporary table,
1508
- Row-based logging is used and it we are creating a temporary table, or
1509
- The binary log is not open.
1510
Otherwise, the statement shall be binlogged.
1513
* Firstly we had a compile problem with MySQL 5.1.42 and
1514
* the write_bin_log() call below:
1515
* discover_xt.cc:1259: error: argument of type 'char* (Statement::)()' does not match 'const char*'
1517
* And secondly, we should no write the BINLOG anyway because this is
1518
* an internal PBXT system table.
1520
* So I am just commenting out the code altogether.
1521
if (!internal_tmp_table &&
1522
(!thd->current_stmt_binlog_row_based ||
1523
(thd->current_stmt_binlog_row_based &&
1524
!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1525
write_bin_log(thd, TRUE, thd->query, thd->query_length);
1529
pthread_mutex_unlock(&LOCK_open);
1532
thd_proc_info(thd, "After create");
1538
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1539
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1541
//create_info->table_existed= 1; // Mark that table existed
1542
goto unlock_and_end;
1545
////////////////////////////////////////////////////////
1546
////// END OF CUT AND PASTES FROM sql_table.cc ////////
1547
////////////////////////////////////////////////////////
1550
#endif // LOCK_OPEN_HACK_REQUIRED
1552
//------------------------------
1553
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)
1556
#define MYLEX_CREATE_INFO create_info
1558
#define MYLEX_CREATE_INFO mylex.create_info
1562
drizzled::statement::AlterTable *stmt = new drizzled::statement::AlterTable(thd);
1563
HA_CREATE_INFO create_info;
1564
//AlterInfo alter_info;
1565
drizzled::message::Table table_proto;
1567
static const char *ext = ".dfe";
1568
static const int ext_len = 4;
1570
table_proto.mutable_engine()->mutable_name()->assign("PBXT");
1572
static const char *ext = ".frm";
1573
static const int ext_len = 4;
1576
char field_length_buffer[12], *field_length_ptr;
1577
LEX *save_lex= thd->lex, mylex;
1579
memset(&MYLEX_CREATE_INFO, 0, sizeof(HA_CREATE_INFO));
1584
mylex.statement = stmt;
1587
/* setup the create info */
1588
MYLEX_CREATE_INFO.db_type = hton;
1591
mylex.create_info.frm_only = 1;
1593
MYLEX_CREATE_INFO.default_table_charset = system_charset_info;
1595
/* setup the column info. */
1596
while (info->field_name) {
1597
LEX_STRING field_name, comment;
1598
field_name.str = (char*)(info->field_name);
1599
field_name.length = strlen(info->field_name);
1601
comment.str = (char*)(info->comment);
1602
comment.length = strlen(info->comment);
1604
if (info->field_length) {
1605
sprintf(field_length_buffer, "%d", info->field_length);
1606
field_length_ptr = field_length_buffer;
1608
field_length_ptr = NULL;
1611
if (add_field_to_list(thd, &field_name, info->field_type, field_length_ptr, info->field_decimal_length,
1613
COLUMN_FORMAT_TYPE_FIXED,
1614
NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
1615
NULL /*interval_list*/, info->field_charset))
1617
if (add_field_to_list(thd, &field_name, info->field_type, field_length_ptr, info->field_decimal_length,
1619
NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
1620
NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/
1621
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID > 50200
1622
, NULL /*vcol_info*/, NULL /* create options */
1632
if (skip_existing) {
1633
size_t db_len = strlen(db);
1634
size_t name_len = strlen(name);
1635
size_t len = db_len + 1 + name_len + ext_len + 1;
1636
char *path = (char *)xt_malloc_ns(len);
1637
memcpy(path, db, db_len);
1638
memcpy(path + db_len + 1, name, name_len);
1639
memcpy(path + db_len + 1 + name_len, ext, ext_len);
1640
path[db_len] = XT_DIR_CHAR;
1641
path[len - 1] = '\0';
1642
xtBool exists = xt_fs_exists(path);
1648
/* Create an internal temp table */
1650
table_proto.set_name(name);
1651
table_proto.set_type(drizzled::message::Table::STANDARD);
1653
if (mysql_create_table_no_lock(thd, db, name, &create_info, &table_proto, &stmt->alter_info, 1, 0))
1656
#ifdef WITH_PARTITION_STORAGE_ENGINE
1657
partition_info *part_info;
1659
part_info = thd->work_part_info;
1660
thd->work_part_info = NULL;
1662
if (mysql_create_table_no_lock(thd, db, name, &mylex.create_info, &mylex.alter_info, 1, 0))
1664
#ifdef WITH_PARTITION_STORAGE_ENGINE
1665
thd->work_part_info = part_info;
1674
thd->lex = save_lex;