~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/pbxt/src/discover_xt.cc

  • Committer: pcrews
  • Date: 2011-05-24 17:36:24 UTC
  • mfrom: (1099.4.232 drizzle)
  • Revision ID: pcrews@lucid32-20110524173624-mwr1bvq6fa1r01ao
Updated translations + 2011.05.18 tarball tag

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
2
 
 * Derived from code Copyright (C) 2000-2004 MySQL AB
3
 
 *
4
 
 * PrimeBase XT
5
 
 *
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.
10
 
 *
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.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
 
 *
20
 
 *  Created by Leslie on 8/27/08.
21
 
 *
22
 
 */
23
 
 
24
 
#include "xt_config.h"
25
 
 
26
 
#ifndef DRIZZLED
27
 
 
28
 
#include "mysql_priv.h"
29
 
#include "item_create.h"
30
 
#include <m_ctype.h>
31
 
 
32
 
#include "strutil_xt.h"
33
 
#include "ha_pbxt.h"
34
 
#include "discover_xt.h"
35
 
#include "ha_xtsys.h"
36
 
 
37
 
#if MYSQL_VERSION_ID >= 50404
38
 
#define DOT_STR(x)                      x.str
39
 
#else
40
 
#define DOT_STR(x)                      x
41
 
#endif
42
 
 
43
 
#define LOCK_OPEN_HACK_REQUIRED
44
 
 
45
 
#ifdef LOCK_OPEN_HACK_REQUIRED
46
 
///////////////////////////////
47
 
/*
48
 
 * Unfortunately I cannot use the standard mysql_create_table_no_lock() because it will lock "LOCK_open"
49
 
 * which has already been locked while the server is performing table discovery. So I have added this hack 
50
 
 * in here to create my own version. The following macros will make the changes I need to get it to work.
51
 
 * The actual function code has been copied here without changes.
52
 
 *
53
 
 * Its almost enough to make you want to cry. :(
54
 
*/
55
 
//-----------------------------
56
 
 
57
 
#ifdef pthread_mutex_lock
58
 
#undef pthread_mutex_lock
59
 
#endif
60
 
 
61
 
#ifdef pthread_mutex_unlock
62
 
#undef pthread_mutex_unlock
63
 
#endif
64
 
 
65
 
#define mysql_create_table_no_lock hacked_mysql_create_table_no_lock
66
 
#define pthread_mutex_lock(l)
67
 
#define pthread_mutex_unlock(l)
68
 
 
69
 
#define check_engine(t, n, c) (0)
70
 
#define set_table_default_charset(t, c, d)
71
 
 
72
 
void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
73
 
                                uint32 *max_length, uint32 *tot_length);
74
 
 
75
 
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen);
76
 
uint build_table_filename(char *buff, size_t bufflen, const char *db,
77
 
                          const char *table_name, const char *ext, uint flags);
78
 
 
79
 
//////////////////////////////////////////////////////////
80
 
////// START OF CUT AND PASTES FROM  sql_table.cc ////////
81
 
//////////////////////////////////////////////////////////
82
 
 
83
 
// sort_keys() cut and pasted directly from sql_table.cc. 
84
 
static int sort_keys(KEY *a, KEY *b)
85
 
{
86
 
  ulong a_flags= a->flags, b_flags= b->flags;
87
 
  
88
 
  if (a_flags & HA_NOSAME)
89
 
  {
90
 
    if (!(b_flags & HA_NOSAME))
91
 
      return -1;
92
 
    if ((a_flags ^ b_flags) & HA_NULL_PART_KEY)
93
 
    {
94
 
      /* Sort NOT NULL keys before other keys */
95
 
      return (a_flags & HA_NULL_PART_KEY) ? 1 : -1;
96
 
    }
97
 
    if (a->name == primary_key_name)
98
 
      return -1;
99
 
    if (b->name == primary_key_name)
100
 
      return 1;
101
 
    /* Sort keys don't containing partial segments before others */
102
 
    if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
103
 
      return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1;
104
 
  }
105
 
  else if (b_flags & HA_NOSAME)
106
 
    return 1;                                   // Prefer b
107
 
 
108
 
  if ((a_flags ^ b_flags) & HA_FULLTEXT)
109
 
  {
110
 
    return (a_flags & HA_FULLTEXT) ? 1 : -1;
111
 
  }
112
 
  /*
113
 
    Prefer original key order.  usable_key_parts contains here
114
 
    the original key position.
115
 
  */
116
 
  return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
117
 
          (a->usable_key_parts > b->usable_key_parts) ? 1 :
118
 
          0);
119
 
}
120
 
 
121
 
// check_if_keyname_exists() cut and pasted directly from sql_table.cc. 
122
 
static bool
123
 
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
124
 
{
125
 
  for (KEY *key=start ; key != end ; key++)
126
 
    if (!my_strcasecmp(system_charset_info,name,key->name))
127
 
      return 1;
128
 
  return 0;
129
 
}
130
 
 
131
 
// make_unique_key_name() cut and pasted directly from sql_table.cc. 
132
 
static char *
133
 
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
134
 
{
135
 
  char buff[MAX_FIELD_NAME],*buff_end;
136
 
 
137
 
  if (!check_if_keyname_exists(field_name,start,end) &&
138
 
      my_strcasecmp(system_charset_info,field_name,primary_key_name))
139
 
    return (char*) field_name;                  // Use fieldname
140
 
  buff_end=strmake(buff,field_name, sizeof(buff)-4);
141
 
 
142
 
  /*
143
 
    Only 3 chars + '\0' left, so need to limit to 2 digit
144
 
    This is ok as we can't have more than 100 keys anyway
145
 
  */
146
 
  for (uint i=2 ; i< 100; i++)
147
 
  {
148
 
    *buff_end= '_';
149
 
    int10_to_str(i, buff_end+1, 10);
150
 
    if (!check_if_keyname_exists(buff,start,end))
151
 
      return sql_strdup(buff);
152
 
  }
153
 
  return (char*) "not_specified";               // Should never happen
154
 
}
155
 
 
156
 
 
157
 
// prepare_blob_field() cut and pasted directly from sql_table.cc. 
158
 
static bool prepare_blob_field(THD *thd, Create_field *sql_field)
159
 
{
160
 
  DBUG_ENTER("prepare_blob_field");
161
 
 
162
 
  if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
163
 
      !(sql_field->flags & BLOB_FLAG))
164
 
  {
165
 
    /* Convert long VARCHAR columns to TEXT or BLOB */
166
 
    char warn_buff[MYSQL_ERRMSG_SIZE];
167
 
 
168
 
    if (sql_field->def || (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
169
 
                                                      MODE_STRICT_ALL_TABLES)))
170
 
    {
171
 
      my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
172
 
               MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
173
 
      DBUG_RETURN(1);
174
 
    }
175
 
    sql_field->sql_type= MYSQL_TYPE_BLOB;
176
 
    sql_field->flags|= BLOB_FLAG;
177
 
    sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
178
 
            (sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
179
 
            (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
180
 
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
181
 
                 warn_buff);
182
 
  }
183
 
    
184
 
  if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
185
 
  {
186
 
    if (sql_field->sql_type == MYSQL_TYPE_BLOB)
187
 
    {
188
 
      /* The user has given a length to the blob column */
189
 
      sql_field->sql_type= get_blob_type_from_length(sql_field->length);
190
 
      sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
191
 
    }
192
 
    sql_field->length= 0;
193
 
  }
194
 
  DBUG_RETURN(0);
195
 
}
196
 
 
197
 
//////////////////////////////
198
 
// mysql_prepare_create_table() cut and pasted directly from sql_table.cc.
199
 
static int
200
 
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
201
 
                           Alter_info *alter_info,
202
 
                           bool tmp_table,
203
 
                           uint *db_options,
204
 
                           handler *file, KEY **key_info_buffer,
205
 
                           uint *key_count, int select_field_count)
206
 
{
207
 
  const char    *key_name;
208
 
  Create_field  *sql_field,*dup_field;
209
 
  uint          field,null_fields,blob_columns,max_key_length;
210
 
  ulong         record_offset= 0;
211
 
  KEY           *key_info;
212
 
  KEY_PART_INFO *key_part_info;
213
 
  int           timestamps= 0, timestamps_with_niladic= 0;
214
 
  int           field_no,dup_no;
215
 
  int           select_field_pos,auto_increment=0;
216
 
  List_iterator<Create_field> it(alter_info->create_list);
217
 
  List_iterator<Create_field> it2(alter_info->create_list);
218
 
  uint total_uneven_bit_length= 0;
219
 
  DBUG_ENTER("mysql_prepare_create_table");
220
 
 
221
 
  select_field_pos= alter_info->create_list.elements - select_field_count;
222
 
  null_fields=blob_columns=0;
223
 
  create_info->varchar= 0;
224
 
  max_key_length= file->max_key_length();
225
 
 
226
 
  for (field_no=0; (sql_field=it++) ; field_no++)
227
 
  {
228
 
    CHARSET_INFO *save_cs;
229
 
 
230
 
    /*
231
 
      Initialize length from its original value (number of characters),
232
 
      which was set in the parser. This is necessary if we're
233
 
      executing a prepared statement for the second time.
234
 
    */
235
 
    sql_field->length= sql_field->char_length;
236
 
    if (!sql_field->charset)
237
 
      sql_field->charset= create_info->default_table_charset;
238
 
    /*
239
 
      table_charset is set in ALTER TABLE if we want change character set
240
 
      for all varchar/char columns.
241
 
      But the table charset must not affect the BLOB fields, so don't
242
 
      allow to change my_charset_bin to somethig else.
243
 
    */
244
 
    if (create_info->table_charset && sql_field->charset != &my_charset_bin)
245
 
      sql_field->charset= create_info->table_charset;
246
 
 
247
 
    save_cs= sql_field->charset;
248
 
    if ((sql_field->flags & BINCMP_FLAG) &&
249
 
        !(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
250
 
                                                    MY_CS_BINSORT,MYF(0))))
251
 
    {
252
 
      char tmp[64];
253
 
      strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
254
 
              STRING_WITH_LEN("_bin"));
255
 
      my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
256
 
      DBUG_RETURN(TRUE);
257
 
    }
258
 
 
259
 
    /*
260
 
      Convert the default value from client character
261
 
      set into the column character set if necessary.
262
 
    */
263
 
    if (sql_field->def && 
264
 
        save_cs != sql_field->def->collation.collation &&
265
 
        (sql_field->sql_type == MYSQL_TYPE_VAR_STRING ||
266
 
         sql_field->sql_type == MYSQL_TYPE_STRING ||
267
 
         sql_field->sql_type == MYSQL_TYPE_SET ||
268
 
         sql_field->sql_type == MYSQL_TYPE_ENUM))
269
 
    {
270
 
      /*
271
 
        Starting from 5.1 we work here with a copy of Create_field
272
 
        created by the caller, not with the instance that was
273
 
        originally created during parsing. It's OK to create
274
 
        a temporary item and initialize with it a member of the
275
 
        copy -- this item will be thrown away along with the copy
276
 
        at the end of execution, and thus not introduce a dangling
277
 
        pointer in the parsed tree of a prepared statement or a
278
 
        stored procedure statement.
279
 
      */
280
 
      sql_field->def= sql_field->def->safe_charset_converter(save_cs);
281
 
 
282
 
      if (sql_field->def == NULL)
283
 
      {
284
 
        /* Could not convert */
285
 
        my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
286
 
        DBUG_RETURN(TRUE);
287
 
      }
288
 
    }
289
 
 
290
 
    if (sql_field->sql_type == MYSQL_TYPE_SET ||
291
 
        sql_field->sql_type == MYSQL_TYPE_ENUM)
292
 
    {
293
 
      uint32 dummy;
294
 
      CHARSET_INFO *cs= sql_field->charset;
295
 
      TYPELIB *interval= sql_field->interval;
296
 
 
297
 
      /*
298
 
        Create typelib from interval_list, and if necessary
299
 
        convert strings from client character set to the
300
 
        column character set.
301
 
      */
302
 
      if (!interval)
303
 
      {
304
 
        /*
305
 
          Create the typelib in runtime memory - we will free the
306
 
          occupied memory at the same time when we free this
307
 
          sql_field -- at the end of execution.
308
 
        */
309
 
        interval= sql_field->interval= typelib(thd->mem_root,
310
 
                                               sql_field->interval_list);
311
 
        List_iterator<String> int_it(sql_field->interval_list);
312
 
        String conv, *tmp;
313
 
        char comma_buf[2];
314
 
        int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
315
 
                                          (uchar*) comma_buf + 
316
 
                                          sizeof(comma_buf));
317
 
        DBUG_ASSERT(comma_length > 0);
318
 
        for (uint i= 0; (tmp= int_it++); i++)
319
 
        {
320
 
          uint lengthsp;
321
 
          if (String::needs_conversion(tmp->length(), tmp->charset(),
322
 
                                       cs, &dummy))
323
 
          {
324
 
            uint cnv_errs;
325
 
            conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
326
 
            interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
327
 
                                                  conv.length());
328
 
            interval->type_lengths[i]= conv.length();
329
 
          }
330
 
 
331
 
          // Strip trailing spaces.
332
 
          lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
333
 
                                       interval->type_lengths[i]);
334
 
          interval->type_lengths[i]= lengthsp;
335
 
          ((uchar *)interval->type_names[i])[lengthsp]= '\0';
336
 
          if (sql_field->sql_type == MYSQL_TYPE_SET)
337
 
          {
338
 
            if (cs->coll->instr(cs, interval->type_names[i], 
339
 
                                interval->type_lengths[i], 
340
 
                                comma_buf, comma_length, NULL, 0))
341
 
            {
342
 
              my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr());
343
 
              DBUG_RETURN(TRUE);
344
 
            }
345
 
          }
346
 
        }
347
 
        sql_field->interval_list.empty(); // Don't need interval_list anymore
348
 
      }
349
 
 
350
 
      if (sql_field->sql_type == MYSQL_TYPE_SET)
351
 
      {
352
 
        uint32 field_length;
353
 
        if (sql_field->def != NULL)
354
 
        {
355
 
          char *not_used;
356
 
          uint not_used2;
357
 
          bool not_found= 0;
358
 
          String str, *def= sql_field->def->val_str(&str);
359
 
          if (def == NULL) /* SQL "NULL" maps to NULL */
360
 
          {
361
 
            if ((sql_field->flags & NOT_NULL_FLAG) != 0)
362
 
            {
363
 
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
364
 
              DBUG_RETURN(TRUE);
365
 
            }
366
 
 
367
 
            /* else, NULL is an allowed value */
368
 
            (void) find_set(interval, NULL, 0,
369
 
                            cs, &not_used, &not_used2, &not_found);
370
 
          }
371
 
          else /* not NULL */
372
 
          {
373
 
            (void) find_set(interval, def->ptr(), def->length(),
374
 
                            cs, &not_used, &not_used2, &not_found);
375
 
          }
376
 
 
377
 
          if (not_found)
378
 
          {
379
 
            my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
380
 
            DBUG_RETURN(TRUE);
381
 
          }
382
 
        }
383
 
        calculate_interval_lengths(cs, interval, &dummy, &field_length);
384
 
        sql_field->length= field_length + (interval->count - 1);
385
 
      }
386
 
      else  /* MYSQL_TYPE_ENUM */
387
 
      {
388
 
        uint32 field_length;
389
 
        DBUG_ASSERT(sql_field->sql_type == MYSQL_TYPE_ENUM);
390
 
        if (sql_field->def != NULL)
391
 
        {
392
 
          String str, *def= sql_field->def->val_str(&str);
393
 
          if (def == NULL) /* SQL "NULL" maps to NULL */
394
 
          {
395
 
            if ((sql_field->flags & NOT_NULL_FLAG) != 0)
396
 
            {
397
 
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
398
 
              DBUG_RETURN(TRUE);
399
 
            }
400
 
 
401
 
            /* else, the defaults yield the correct length for NULLs. */
402
 
          } 
403
 
          else /* not NULL */
404
 
          {
405
 
            def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
406
 
            if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
407
 
            {
408
 
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
409
 
              DBUG_RETURN(TRUE);
410
 
            }
411
 
          }
412
 
        }
413
 
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
414
 
        sql_field->length= field_length;
415
 
      }
416
 
      set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
417
 
    }
418
 
 
419
 
    if (sql_field->sql_type == MYSQL_TYPE_BIT)
420
 
    { 
421
 
      sql_field->pack_flag= FIELDFLAG_NUMBER;
422
 
      if (file->ha_table_flags() & HA_CAN_BIT_FIELD)
423
 
        total_uneven_bit_length+= sql_field->length & 7;
424
 
      else
425
 
        sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
426
 
    }
427
 
 
428
 
    sql_field->create_length_to_internal_length();
429
 
    if (prepare_blob_field(thd, sql_field))
430
 
      DBUG_RETURN(TRUE);
431
 
 
432
 
    if (!(sql_field->flags & NOT_NULL_FLAG))
433
 
      null_fields++;
434
 
 
435
 
    if (check_column_name(sql_field->field_name))
436
 
    {
437
 
      my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
438
 
      DBUG_RETURN(TRUE);
439
 
    }
440
 
 
441
 
    /* Check if we have used the same field name before */
442
 
    for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
443
 
    {
444
 
      if (my_strcasecmp(system_charset_info,
445
 
                        sql_field->field_name,
446
 
                        dup_field->field_name) == 0)
447
 
      {
448
 
        /*
449
 
          If this was a CREATE ... SELECT statement, accept a field
450
 
          redefinition if we are changing a field in the SELECT part
451
 
        */
452
 
        if (field_no < select_field_pos || dup_no >= select_field_pos)
453
 
        {
454
 
          my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
455
 
          DBUG_RETURN(TRUE);
456
 
        }
457
 
        else
458
 
        {
459
 
          /* Field redefined */
460
 
          sql_field->def=               dup_field->def;
461
 
          sql_field->sql_type=          dup_field->sql_type;
462
 
          sql_field->charset=           (dup_field->charset ?
463
 
                                         dup_field->charset :
464
 
                                         create_info->default_table_charset);
465
 
          sql_field->length=            dup_field->char_length;
466
 
          sql_field->pack_length=       dup_field->pack_length;
467
 
          sql_field->key_length=        dup_field->key_length;
468
 
          sql_field->decimals=          dup_field->decimals;
469
 
          sql_field->create_length_to_internal_length();
470
 
          sql_field->unireg_check=      dup_field->unireg_check;
471
 
          /* 
472
 
            We're making one field from two, the result field will have
473
 
            dup_field->flags as flags. If we've incremented null_fields
474
 
            because of sql_field->flags, decrement it back.
475
 
          */
476
 
          if (!(sql_field->flags & NOT_NULL_FLAG))
477
 
            null_fields--;
478
 
          sql_field->flags=             dup_field->flags;
479
 
          sql_field->interval=          dup_field->interval;
480
 
          it2.remove();                 // Remove first (create) definition
481
 
          select_field_pos--;
482
 
          break;
483
 
        }
484
 
      }
485
 
    }
486
 
    /* Don't pack rows in old tables if the user has requested this */
487
 
    if ((sql_field->flags & BLOB_FLAG) ||
488
 
        (sql_field->sql_type == MYSQL_TYPE_VARCHAR &&
489
 
         create_info->row_type != ROW_TYPE_FIXED))
490
 
      (*db_options)|= HA_OPTION_PACK_RECORD;
491
 
    it2.rewind();
492
 
  }
493
 
 
494
 
  /* record_offset will be increased with 'length-of-null-bits' later */
495
 
  record_offset= 0;
496
 
  null_fields+= total_uneven_bit_length;
497
 
 
498
 
  it.rewind();
499
 
  while ((sql_field=it++))
500
 
  {
501
 
    DBUG_ASSERT(sql_field->charset != 0);
502
 
 
503
 
    if (prepare_create_field(sql_field, &blob_columns, 
504
 
                             &timestamps, &timestamps_with_niladic,
505
 
                             file->ha_table_flags()))
506
 
      DBUG_RETURN(TRUE);
507
 
    if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
508
 
      create_info->varchar= TRUE;
509
 
    sql_field->offset= record_offset;
510
 
    if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
511
 
      auto_increment++;
512
 
    record_offset+= sql_field->pack_length;
513
 
  }
514
 
  if (timestamps_with_niladic > 1)
515
 
  {
516
 
    my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
517
 
               ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
518
 
    DBUG_RETURN(TRUE);
519
 
  }
520
 
  if (auto_increment > 1)
521
 
  {
522
 
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
523
 
    DBUG_RETURN(TRUE);
524
 
  }
525
 
  if (auto_increment &&
526
 
      (file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
527
 
  {
528
 
    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
529
 
               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
530
 
    DBUG_RETURN(TRUE);
531
 
  }
532
 
 
533
 
  if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
534
 
  {
535
 
    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
536
 
               MYF(0));
537
 
    DBUG_RETURN(TRUE);
538
 
  }
539
 
 
540
 
  /* Create keys */
541
 
 
542
 
  List_iterator<Key> key_iterator(alter_info->key_list);
543
 
  List_iterator<Key> key_iterator2(alter_info->key_list);
544
 
  uint key_parts=0, fk_key_count=0;
545
 
  bool primary_key=0,unique_key=0;
546
 
  Key *key, *key2;
547
 
  uint tmp, key_number;
548
 
  /* special marker for keys to be ignored */
549
 
  static char ignore_key[1];
550
 
 
551
 
  /* Calculate number of key segements */
552
 
  *key_count= 0;
553
 
  
554
 
  while ((key=key_iterator++))
555
 
  {
556
 
    DBUG_PRINT("info", ("key name: '%s'  type: %d", key->DOT_STR(name) ? key->DOT_STR(name) :
557
 
                        "(none)" , key->type));
558
 
    LEX_STRING key_name_str;
559
 
    if (key->type == Key::FOREIGN_KEY)
560
 
    {
561
 
      fk_key_count++;
562
 
      Foreign_key *fk_key= (Foreign_key*) key;
563
 
      if (fk_key->ref_columns.elements &&
564
 
          fk_key->ref_columns.elements != fk_key->columns.elements)
565
 
      {
566
 
        my_error(ER_WRONG_FK_DEF, MYF(0),
567
 
                 (fk_key->DOT_STR(name) ?  fk_key->DOT_STR(name) : "foreign key without name"),
568
 
                 ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
569
 
        DBUG_RETURN(TRUE);
570
 
      }
571
 
      continue;
572
 
    }
573
 
    (*key_count)++;
574
 
    tmp=file->max_key_parts();
575
 
    if (key->columns.elements > tmp)
576
 
    {
577
 
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
578
 
      DBUG_RETURN(TRUE);
579
 
    }
580
 
    key_name_str.str= (char*) key->DOT_STR(name);
581
 
    key_name_str.length= key->DOT_STR(name) ? strlen(key->DOT_STR(name)) : 0;
582
 
    if (check_string_char_length(&key_name_str, "", NAME_CHAR_LEN,
583
 
                                 system_charset_info, 1))
584
 
    {
585
 
      my_error(ER_TOO_LONG_IDENT, MYF(0), key->DOT_STR(name));
586
 
      DBUG_RETURN(TRUE);
587
 
    }
588
 
    key_iterator2.rewind ();
589
 
    if (key->type != Key::FOREIGN_KEY)
590
 
    {
591
 
      while ((key2 = key_iterator2++) != key)
592
 
      {
593
 
        /*
594
 
          foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is
595
 
          'generated', and a generated key is a prefix of the other key.
596
 
          Then we do not need the generated shorter key.
597
 
        */
598
 
        if ((key2->type != Key::FOREIGN_KEY &&
599
 
             key2->DOT_STR(name) != ignore_key &&
600
 
             !foreign_key_prefix(key, key2)))
601
 
        {
602
 
          /* TODO: issue warning message */
603
 
          /* mark that the generated key should be ignored */
604
 
          if (!key2->generated ||
605
 
              (key->generated && key->columns.elements <
606
 
               key2->columns.elements))
607
 
            key->DOT_STR(name)= ignore_key;
608
 
          else
609
 
          {
610
 
            key2->DOT_STR(name)= ignore_key;
611
 
            key_parts-= key2->columns.elements;
612
 
            (*key_count)--;
613
 
          }
614
 
          break;
615
 
        }
616
 
      }
617
 
    }
618
 
    if (key->DOT_STR(name) != ignore_key)
619
 
      key_parts+=key->columns.elements;
620
 
    else
621
 
      (*key_count)--;
622
 
    if (key->DOT_STR(name) && !tmp_table && (key->type != Key::PRIMARY) &&
623
 
        !my_strcasecmp(system_charset_info,key->DOT_STR(name),primary_key_name))
624
 
    {
625
 
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->DOT_STR(name));
626
 
      DBUG_RETURN(TRUE);
627
 
    }
628
 
  }
629
 
  tmp=file->max_keys();
630
 
  if (*key_count > tmp)
631
 
  {
632
 
    my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
633
 
    DBUG_RETURN(TRUE);
634
 
  }
635
 
 
636
 
  (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
637
 
  key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
638
 
  if (!*key_info_buffer || ! key_part_info)
639
 
    DBUG_RETURN(TRUE);                          // Out of memory
640
 
 
641
 
  key_iterator.rewind();
642
 
  key_number=0;
643
 
  for (; (key=key_iterator++) ; key_number++)
644
 
  {
645
 
    uint key_length=0;
646
 
    Key_part_spec *column;
647
 
 
648
 
    if (key->DOT_STR(name) == ignore_key)
649
 
    {
650
 
      /* ignore redundant keys */
651
 
      do
652
 
        key=key_iterator++;
653
 
      while (key && key->DOT_STR(name) == ignore_key);
654
 
      if (!key)
655
 
        break;
656
 
    }
657
 
 
658
 
    switch (key->type) {
659
 
    case Key::MULTIPLE:
660
 
        key_info->flags= 0;
661
 
        break;
662
 
    case Key::FULLTEXT:
663
 
        key_info->flags= HA_FULLTEXT;
664
 
        if ((key_info->parser_name= &key->key_create_info.parser_name)->str)
665
 
          key_info->flags|= HA_USES_PARSER;
666
 
        else
667
 
          key_info->parser_name= 0;
668
 
        break;
669
 
    case Key::SPATIAL:
670
 
#ifdef HAVE_SPATIAL
671
 
        key_info->flags= HA_SPATIAL;
672
 
        break;
673
 
#else
674
 
        my_error(ER_FEATURE_DISABLED, MYF(0),
675
 
                 sym_group_geom.name, sym_group_geom.needed_define);
676
 
        DBUG_RETURN(TRUE);
677
 
#endif
678
 
    case Key::FOREIGN_KEY:
679
 
      key_number--;                             // Skip this key
680
 
      continue;
681
 
    default:
682
 
      key_info->flags = HA_NOSAME;
683
 
      break;
684
 
    }
685
 
    if (key->generated)
686
 
      key_info->flags|= HA_GENERATED_KEY;
687
 
 
688
 
    key_info->key_parts=(uint8) key->columns.elements;
689
 
    key_info->key_part=key_part_info;
690
 
    key_info->usable_key_parts= key_number;
691
 
    key_info->algorithm= key->key_create_info.algorithm;
692
 
 
693
 
    if (key->type == Key::FULLTEXT)
694
 
    {
695
 
      if (!(file->ha_table_flags() & HA_CAN_FULLTEXT))
696
 
      {
697
 
        my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT),
698
 
                   MYF(0));
699
 
        DBUG_RETURN(TRUE);
700
 
      }
701
 
    }
702
 
    /*
703
 
       Make SPATIAL to be RTREE by default
704
 
       SPATIAL only on BLOB or at least BINARY, this
705
 
       actually should be replaced by special GEOM type
706
 
       in near future when new frm file is ready
707
 
       checking for proper key parts number:
708
 
    */
709
 
 
710
 
    /* TODO: Add proper checks if handler supports key_type and algorithm */
711
 
    if (key_info->flags & HA_SPATIAL)
712
 
    {
713
 
      if (!(file->ha_table_flags() & HA_CAN_RTREEKEYS))
714
 
      {
715
 
        my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS),
716
 
                   MYF(0));
717
 
        DBUG_RETURN(TRUE);
718
 
      }
719
 
      if (key_info->key_parts != 1)
720
 
      {
721
 
        my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
722
 
        DBUG_RETURN(TRUE);
723
 
      }
724
 
    }
725
 
    else if (key_info->algorithm == HA_KEY_ALG_RTREE)
726
 
    {
727
 
#ifdef HAVE_RTREE_KEYS
728
 
      if ((key_info->key_parts & 1) == 1)
729
 
      {
730
 
        my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX");
731
 
        DBUG_RETURN(TRUE);
732
 
      }
733
 
      /* TODO: To be deleted */
734
 
      my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX");
735
 
      DBUG_RETURN(TRUE);
736
 
#else
737
 
      my_error(ER_FEATURE_DISABLED, MYF(0),
738
 
               sym_group_rtree.name, sym_group_rtree.needed_define);
739
 
      DBUG_RETURN(TRUE);
740
 
#endif
741
 
    }
742
 
 
743
 
    /* Take block size from key part or table part */
744
 
    /*
745
 
      TODO: Add warning if block size changes. We can't do it here, as
746
 
      this may depend on the size of the key
747
 
    */
748
 
    key_info->block_size= (key->key_create_info.block_size ?
749
 
                           key->key_create_info.block_size :
750
 
                           create_info->key_block_size);
751
 
 
752
 
    if (key_info->block_size)
753
 
      key_info->flags|= HA_USES_BLOCK_SIZE;
754
 
 
755
 
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
756
 
    CHARSET_INFO *ft_key_charset=0;  // for FULLTEXT
757
 
    for (uint column_nr=0 ; (column=cols++) ; column_nr++)
758
 
    {
759
 
      uint length;
760
 
      Key_part_spec *dup_column;
761
 
 
762
 
      it.rewind();
763
 
      field=0;
764
 
      while ((sql_field=it++) &&
765
 
             my_strcasecmp(system_charset_info,
766
 
                           column->DOT_STR(field_name),
767
 
                           sql_field->field_name))
768
 
        field++;
769
 
      if (!sql_field)
770
 
      {
771
 
        my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
772
 
        DBUG_RETURN(TRUE);
773
 
      }
774
 
      while ((dup_column= cols2++) != column)
775
 
      {
776
 
        if (!my_strcasecmp(system_charset_info,
777
 
                           column->DOT_STR(field_name), dup_column->DOT_STR(field_name)))
778
 
        {
779
 
          my_printf_error(ER_DUP_FIELDNAME,
780
 
                          ER(ER_DUP_FIELDNAME),MYF(0),
781
 
                          column->field_name);
782
 
          DBUG_RETURN(TRUE);
783
 
        }
784
 
      }
785
 
      cols2.rewind();
786
 
      if (key->type == Key::FULLTEXT)
787
 
      {
788
 
        if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
789
 
             sql_field->sql_type != MYSQL_TYPE_VARCHAR &&
790
 
             !f_is_blob(sql_field->pack_flag)) ||
791
 
            sql_field->charset == &my_charset_bin ||
792
 
            sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
793
 
            (ft_key_charset && sql_field->charset != ft_key_charset))
794
 
        {
795
 
            my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name);
796
 
            DBUG_RETURN(-1);
797
 
        }
798
 
        ft_key_charset=sql_field->charset;
799
 
        /*
800
 
          for fulltext keys keyseg length is 1 for blobs (it's ignored in ft
801
 
          code anyway, and 0 (set to column width later) for char's. it has
802
 
          to be correct col width for char's, as char data are not prefixed
803
 
          with length (unlike blobs, where ft code takes data length from a
804
 
          data prefix, ignoring column->length).
805
 
        */
806
 
        column->length=test(f_is_blob(sql_field->pack_flag));
807
 
      }
808
 
      else
809
 
      {
810
 
        column->length*= sql_field->charset->mbmaxlen;
811
 
 
812
 
        if (key->type == Key::SPATIAL && column->length)
813
 
        {
814
 
          my_error(ER_WRONG_SUB_KEY, MYF(0));
815
 
          DBUG_RETURN(TRUE);
816
 
        }
817
 
 
818
 
        if (f_is_blob(sql_field->pack_flag) ||
819
 
            (f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
820
 
        {
821
 
          if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
822
 
          {
823
 
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name);
824
 
            DBUG_RETURN(TRUE);
825
 
          }
826
 
          if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
827
 
              Field::GEOM_POINT)
828
 
            column->length= 25;
829
 
          if (!column->length)
830
 
          {
831
 
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name);
832
 
            DBUG_RETURN(TRUE);
833
 
          }
834
 
        }
835
 
#ifdef HAVE_SPATIAL
836
 
        if (key->type == Key::SPATIAL)
837
 
        {
838
 
          if (!column->length)
839
 
          {
840
 
            /*
841
 
              4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
842
 
              Lately we'll extend this code to support more dimensions
843
 
            */
844
 
            column->length= 4*sizeof(double);
845
 
          }
846
 
        }
847
 
#endif
848
 
        if (!(sql_field->flags & NOT_NULL_FLAG))
849
 
        {
850
 
          if (key->type == Key::PRIMARY)
851
 
          {
852
 
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
853
 
            sql_field->flags|= NOT_NULL_FLAG;
854
 
            sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
855
 
            null_fields--;
856
 
          }
857
 
          else
858
 
          {
859
 
            key_info->flags|= HA_NULL_PART_KEY;
860
 
            if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
861
 
            {
862
 
              my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name);
863
 
              DBUG_RETURN(TRUE);
864
 
            }
865
 
            if (key->type == Key::SPATIAL)
866
 
            {
867
 
              my_message(ER_SPATIAL_CANT_HAVE_NULL,
868
 
                         ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
869
 
              DBUG_RETURN(TRUE);
870
 
            }
871
 
          }
872
 
        }
873
 
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
874
 
        {
875
 
          if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
876
 
            auto_increment--;                   // Field is used
877
 
        }
878
 
      }
879
 
 
880
 
      key_part_info->fieldnr= field;
881
 
      key_part_info->offset=  (uint16) sql_field->offset;
882
 
      key_part_info->key_type=sql_field->pack_flag;
883
 
      length= sql_field->key_length;
884
 
 
885
 
      if (column->length)
886
 
      {
887
 
        if (f_is_blob(sql_field->pack_flag))
888
 
        {
889
 
          if ((length=column->length) > max_key_length ||
890
 
              length > file->max_key_part_length())
891
 
          {
892
 
            length=min(max_key_length, file->max_key_part_length());
893
 
            if (key->type == Key::MULTIPLE)
894
 
            {
895
 
              /* not a critical problem */
896
 
              char warn_buff[MYSQL_ERRMSG_SIZE];
897
 
              my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
898
 
                          length);
899
 
              push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
900
 
                           ER_TOO_LONG_KEY, warn_buff);
901
 
              /* Align key length to multibyte char boundary */
902
 
              length-= length % sql_field->charset->mbmaxlen;
903
 
            }
904
 
            else
905
 
            {
906
 
              my_error(ER_TOO_LONG_KEY,MYF(0),length);
907
 
              DBUG_RETURN(TRUE);
908
 
            }
909
 
          }
910
 
        }
911
 
        else if (!f_is_geom(sql_field->pack_flag) &&
912
 
                  (column->length > length ||
913
 
                   !Field::type_can_have_key_part (sql_field->sql_type) ||
914
 
                   ((f_is_packed(sql_field->pack_flag) ||
915
 
                     ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
916
 
                      (key_info->flags & HA_NOSAME))) &&
917
 
                    column->length != length)))
918
 
        {
919
 
          my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
920
 
          DBUG_RETURN(TRUE);
921
 
        }
922
 
        else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
923
 
          length=column->length;
924
 
      }
925
 
      else if (length == 0)
926
 
      {
927
 
        my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name);
928
 
          DBUG_RETURN(TRUE);
929
 
      }
930
 
      if (length > file->max_key_part_length() && key->type != Key::FULLTEXT)
931
 
      {
932
 
        length= file->max_key_part_length();
933
 
        if (key->type == Key::MULTIPLE)
934
 
        {
935
 
          /* not a critical problem */
936
 
          char warn_buff[MYSQL_ERRMSG_SIZE];
937
 
          my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
938
 
                      length);
939
 
          push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
940
 
                       ER_TOO_LONG_KEY, warn_buff);
941
 
          /* Align key length to multibyte char boundary */
942
 
          length-= length % sql_field->charset->mbmaxlen;
943
 
        }
944
 
        else
945
 
        {
946
 
          my_error(ER_TOO_LONG_KEY,MYF(0),length);
947
 
          DBUG_RETURN(TRUE);
948
 
        }
949
 
      }
950
 
      key_part_info->length=(uint16) length;
951
 
      /* Use packed keys for long strings on the first column */
952
 
      if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
953
 
          (length >= KEY_DEFAULT_PACK_LENGTH &&
954
 
           (sql_field->sql_type == MYSQL_TYPE_STRING ||
955
 
            sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
956
 
            sql_field->pack_flag & FIELDFLAG_BLOB)))
957
 
      {
958
 
        if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
959
 
            sql_field->sql_type == MYSQL_TYPE_VARCHAR)
960
 
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
961
 
        else
962
 
          key_info->flags|= HA_PACK_KEY;
963
 
      }
964
 
      /* Check if the key segment is partial, set the key flag accordingly */
965
 
      if (length != sql_field->key_length)
966
 
        key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
967
 
 
968
 
      key_length+=length;
969
 
      key_part_info++;
970
 
 
971
 
      /* Create the key name based on the first column (if not given) */
972
 
      if (column_nr == 0)
973
 
      {
974
 
        if (key->type == Key::PRIMARY)
975
 
        {
976
 
          if (primary_key)
977
 
          {
978
 
            my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
979
 
                       MYF(0));
980
 
            DBUG_RETURN(TRUE);
981
 
          }
982
 
          key_name=primary_key_name;
983
 
          primary_key=1;
984
 
        }
985
 
        else if (!(key_name = key->DOT_STR(name)))
986
 
          key_name=make_unique_key_name(sql_field->field_name,
987
 
                                        *key_info_buffer, key_info);
988
 
        if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
989
 
        {
990
 
          my_error(ER_DUP_KEYNAME, MYF(0), key_name);
991
 
          DBUG_RETURN(TRUE);
992
 
        }
993
 
        key_info->name=(char*) key_name;
994
 
      }
995
 
    }
996
 
    if (!key_info->name || check_column_name(key_info->name))
997
 
    {
998
 
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
999
 
      DBUG_RETURN(TRUE);
1000
 
    }
1001
 
    if (!(key_info->flags & HA_NULL_PART_KEY))
1002
 
      unique_key=1;
1003
 
    key_info->key_length=(uint16) key_length;
1004
 
    if (key_length > max_key_length && key->type != Key::FULLTEXT)
1005
 
    {
1006
 
      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1007
 
      DBUG_RETURN(TRUE);
1008
 
    }
1009
 
    key_info++;
1010
 
  }
1011
 
  if (!unique_key && !primary_key &&
1012
 
      (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1013
 
  {
1014
 
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1015
 
    DBUG_RETURN(TRUE);
1016
 
  }
1017
 
  if (auto_increment > 0)
1018
 
  {
1019
 
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1020
 
    DBUG_RETURN(TRUE);
1021
 
  }
1022
 
  /* Sort keys in optimized order */
1023
 
  my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
1024
 
           (qsort_cmp) sort_keys);
1025
 
  create_info->null_bits= null_fields;
1026
 
 
1027
 
  /* Check fields. */
1028
 
  it.rewind();
1029
 
  while ((sql_field=it++))
1030
 
  {
1031
 
    Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1032
 
 
1033
 
    if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
1034
 
        !sql_field->def &&
1035
 
        sql_field->sql_type == MYSQL_TYPE_TIMESTAMP &&
1036
 
        (sql_field->flags & NOT_NULL_FLAG) &&
1037
 
        (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1038
 
    {
1039
 
      /*
1040
 
        An error should be reported if:
1041
 
          - NO_ZERO_DATE SQL mode is active;
1042
 
          - there is no explicit DEFAULT clause (default column value);
1043
 
          - this is a TIMESTAMP column;
1044
 
          - the column is not NULL;
1045
 
          - this is not the DEFAULT CURRENT_TIMESTAMP column.
1046
 
 
1047
 
        In other words, an error should be reported if
1048
 
          - NO_ZERO_DATE SQL mode is active;
1049
 
          - the column definition is equivalent to
1050
 
            'column_name TIMESTAMP DEFAULT 0'.
1051
 
      */
1052
 
 
1053
 
      my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
1054
 
      DBUG_RETURN(TRUE);
1055
 
    }
1056
 
  }
1057
 
 
1058
 
  DBUG_RETURN(FALSE);
1059
 
}
1060
 
 
1061
 
//////////////////////////////
1062
 
// mysql_create_table_no_lock() cut and pasted directly from sql_table.cc. (I did make is static after copying it.)
1063
 
 
1064
 
static bool mysql_create_table_no_lock(THD *thd,
1065
 
                                const char *db, const char *table_name,
1066
 
                                HA_CREATE_INFO *create_info,
1067
 
                                Alter_info *alter_info,
1068
 
                                bool internal_tmp_table,
1069
 
                                uint select_field_count)
1070
 
{
1071
 
  char                  path[FN_REFLEN];
1072
 
  uint          path_length;
1073
 
  const char    *alias;
1074
 
  uint                  db_options, key_count;
1075
 
  KEY                   *key_info_buffer;
1076
 
  handler               *file;
1077
 
  bool                  error= TRUE;
1078
 
  DBUG_ENTER("mysql_create_table_no_lock");
1079
 
  DBUG_PRINT("enter", ("db: '%s'  table: '%s'  tmp: %d",
1080
 
                       db, table_name, internal_tmp_table));
1081
 
 
1082
 
 
1083
 
  /* Check for duplicate fields and check type of table to create */
1084
 
  if (!alter_info->create_list.elements)
1085
 
  {
1086
 
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1087
 
               MYF(0));
1088
 
    DBUG_RETURN(TRUE);
1089
 
  }
1090
 
  if (check_engine(thd, table_name, create_info))
1091
 
    DBUG_RETURN(TRUE);
1092
 
  db_options= create_info->table_options;
1093
 
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
1094
 
    db_options|=HA_OPTION_PACK_RECORD;
1095
 
  alias= table_case_name(create_info, table_name);
1096
 
 
1097
 
  /* PMC - Done to avoid getting the partition handler by mistake! */
1098
 
  if (!(file= new (thd->mem_root) ha_xtsys(pbxt_hton, NULL)))
1099
 
  {
1100
 
    mem_alloc_error(sizeof(handler));
1101
 
    DBUG_RETURN(TRUE);
1102
 
  }
1103
 
 
1104
 
  set_table_default_charset(thd, create_info, (char*) db);
1105
 
 
1106
 
  if (mysql_prepare_create_table(thd, create_info, alter_info,
1107
 
                                 internal_tmp_table,
1108
 
                                 &db_options, file,
1109
 
                                 &key_info_buffer, &key_count,
1110
 
                                 select_field_count))
1111
 
    goto err;
1112
 
 
1113
 
      /* Check if table exists */
1114
 
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1115
 
  {
1116
 
    path_length= build_tmptable_filename(thd, path, sizeof(path));
1117
 
    create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
1118
 
  }
1119
 
  else  
1120
 
  {
1121
 
 #ifdef FN_DEVCHAR
1122
 
    /* check if the table name contains FN_DEVCHAR when defined */
1123
 
    if (strchr(alias, FN_DEVCHAR))
1124
 
    {
1125
 
      my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
1126
 
      DBUG_RETURN(TRUE);
1127
 
    }
1128
 
#endif
1129
 
    path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
1130
 
                                      internal_tmp_table ? FN_IS_TMP : 0);
1131
 
  }
1132
 
 
1133
 
  /* Check if table already exists */
1134
 
  if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1135
 
      find_temporary_table(thd, db, table_name))
1136
 
  {
1137
 
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1138
 
    {
1139
 
      create_info->table_existed= 1;            // Mark that table existed
1140
 
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1141
 
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1142
 
                          alias);
1143
 
      error= 0;
1144
 
      goto err;
1145
 
    }
1146
 
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
1147
 
    goto err;
1148
 
  }
1149
 
 
1150
 
  MYSQL_LOCK(LOCK_open);
1151
 
  if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1152
 
  {
1153
 
    if (!access(path,F_OK))
1154
 
    {
1155
 
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1156
 
        goto warn;
1157
 
      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1158
 
      goto unlock_and_end;
1159
 
    }
1160
 
    /*
1161
 
      We don't assert here, but check the result, because the table could be
1162
 
      in the table definition cache and in the same time the .frm could be
1163
 
      missing from the disk, in case of manual intervention which deletes
1164
 
      the .frm file. The user has to use FLUSH TABLES; to clear the cache.
1165
 
      Then she could create the table. This case is pretty obscure and
1166
 
      therefore we don't introduce a new error message only for it.
1167
 
    */
1168
 
    if (get_cached_table_share(db, alias))
1169
 
    {
1170
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1171
 
      goto unlock_and_end;
1172
 
    }
1173
 
  }
1174
 
 
1175
 
  /*
1176
 
    Check that table with given name does not already
1177
 
    exist in any storage engine. In such a case it should
1178
 
    be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1179
 
    unless user specified CREATE TABLE IF EXISTS
1180
 
    The LOCK_open mutex has been locked to make sure no
1181
 
    one else is attempting to discover the table. Since
1182
 
    it's not on disk as a frm file, no one could be using it!
1183
 
  */
1184
 
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1185
 
  {
1186
 
    bool create_if_not_exists =
1187
 
      create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
1188
 
    int retcode = ha_table_exists_in_engine(thd, db, table_name);
1189
 
    DBUG_PRINT("info", ("exists_in_engine: %u",retcode));
1190
 
    switch (retcode)
1191
 
    {
1192
 
      case HA_ERR_NO_SUCH_TABLE:
1193
 
        /* Normal case, no table exists. we can go and create it */
1194
 
        break;
1195
 
      case HA_ERR_TABLE_EXIST:
1196
 
        DBUG_PRINT("info", ("Table existed in handler"));
1197
 
 
1198
 
        if (create_if_not_exists)
1199
 
          goto warn;
1200
 
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1201
 
        goto unlock_and_end;
1202
 
        break;
1203
 
      default:
1204
 
        DBUG_PRINT("info", ("error: %u from storage engine", retcode));
1205
 
        my_error(retcode, MYF(0),table_name);
1206
 
        goto unlock_and_end;
1207
 
    }
1208
 
  }
1209
 
 
1210
 
  thd_proc_info(thd, "creating table");
1211
 
  create_info->table_existed= 0;                // Mark that table is created
1212
 
 
1213
 
  create_info->table_options=db_options;
1214
 
 
1215
 
  path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
1216
 
  if (rea_create_table(thd, path, db, table_name,
1217
 
                       create_info, alter_info->create_list,
1218
 
                       key_count, key_info_buffer, file))
1219
 
    goto unlock_and_end;
1220
 
 
1221
 
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1222
 
  {
1223
 
    /* Open table and put in temporary table list */
1224
 
#if MYSQL_VERSION_ID >= 50404
1225
 
    if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
1226
 
#else
1227
 
    if (!(open_temporary_table(thd, path, db, table_name, 1)))
1228
 
#endif
1229
 
    {
1230
 
#if MYSQL_VERSION_ID >= 50404
1231
 
      (void) rm_temporary_table(create_info->db_type, path, false);
1232
 
#else
1233
 
      (void) rm_temporary_table(create_info->db_type, path);
1234
 
#endif
1235
 
      goto unlock_and_end;
1236
 
    }
1237
 
    thd->thread_specific_used= TRUE;
1238
 
  }
1239
 
 
1240
 
  /*
1241
 
    Don't write statement if:
1242
 
    - It is an internal temporary table,
1243
 
    - Row-based logging is used and it we are creating a temporary table, or
1244
 
    - The binary log is not open.
1245
 
    Otherwise, the statement shall be binlogged.
1246
 
   */
1247
 
  /* PBXT 1.0.09e
1248
 
   * Firstly we had a compile problem with MySQL 5.1.42 and
1249
 
   * the write_bin_log() call below:
1250
 
   * discover_xt.cc:1259: error: argument of type 'char* (Statement::)()' does not match 'const char*'
1251
 
   * 
1252
 
   * And secondly, we should no write the BINLOG anyway because this is
1253
 
   * an internal PBXT system table.
1254
 
   *
1255
 
   * So I am just commenting out the code altogether.
1256
 
  if (!internal_tmp_table &&
1257
 
      (!thd->current_stmt_binlog_row_based ||
1258
 
       (thd->current_stmt_binlog_row_based &&
1259
 
        !(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1260
 
    write_bin_log(thd, TRUE, thd->query, thd->query_length);
1261
 
   */
1262
 
  error= FALSE;
1263
 
unlock_and_end:
1264
 
  MYSQL_UNLOCK(LOCK_open);
1265
 
 
1266
 
err:
1267
 
  thd_proc_info(thd, "After create");
1268
 
  delete file;
1269
 
  DBUG_RETURN(error);
1270
 
 
1271
 
warn:
1272
 
  error= FALSE;
1273
 
  push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1274
 
                      ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1275
 
                      alias);
1276
 
  create_info->table_existed= 1;                // Mark that table existed
1277
 
  goto unlock_and_end;
1278
 
}
1279
 
 
1280
 
////////////////////////////////////////////////////////
1281
 
////// END OF CUT AND PASTES FROM  sql_table.cc ////////
1282
 
////////////////////////////////////////////////////////
1283
 
 
1284
 
#endif // LOCK_OPEN_HACK_REQUIRED
1285
 
 
1286
 
//------------------------------
1287
 
int xt_create_table_frm(handlerton *hton, THD* thd, const char *db, const char *name, DT_FIELD_INFO *info, DT_KEY_INFO *XT_UNUSED(keys), xtBool skip_existing)
1288
 
{
1289
 
        static const char *ext = ".frm";
1290
 
        static const int ext_len = 4;
1291
 
        int err = 1;
1292
 
        char field_length_buffer[12], *field_length_ptr;
1293
 
        LEX  *save_lex= thd->lex, mylex;
1294
 
 
1295
 
        memset(&mylex.create_info, 0, sizeof(HA_CREATE_INFO));
1296
 
 
1297
 
        thd->lex = &mylex;
1298
 
        lex_start(thd);
1299
 
        
1300
 
        /* setup the create info */
1301
 
        mylex.create_info.db_type = hton;
1302
 
 
1303
 
        mylex.create_info.frm_only = 1;
1304
 
        mylex.create_info.default_table_charset = system_charset_info;
1305
 
        
1306
 
        /* setup the column info. */
1307
 
        while (info->field_name) {              
1308
 
                 LEX_STRING field_name, comment;                 
1309
 
                 field_name.str = (char*)(info->field_name);
1310
 
                 field_name.length = strlen(info->field_name);
1311
 
                 
1312
 
                 comment.str = (char*)(info->comment);
1313
 
                 comment.length = strlen(info->comment);
1314
 
                                        
1315
 
                 if (info->field_length) {
1316
 
                        sprintf(field_length_buffer, "%d", info->field_length);
1317
 
                        field_length_ptr = field_length_buffer;
1318
 
                 } else 
1319
 
                        field_length_ptr = NULL;
1320
 
 
1321
 
                if (add_field_to_list(thd, &field_name, info->field_type, field_length_ptr, info->field_decimal_length,
1322
 
                        info->field_flags,
1323
 
#if MYSQL_VERSION_ID >= 50404
1324
 
                                HA_SM_DISK,
1325
 
                                COLUMN_FORMAT_TYPE_FIXED,
1326
 
#endif
1327
 
                       NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/, 
1328
 
                       NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/
1329
 
#ifdef MARIADB_BASE_VERSION
1330
 
                       , NULL /*vcol_info*/, NULL /* create options */
1331
 
#endif
1332
 
                       )) 
1333
 
                        goto error;
1334
 
 
1335
 
 
1336
 
                info++;
1337
 
        }
1338
 
 
1339
 
        if (skip_existing) {
1340
 
                size_t db_len = strlen(db);
1341
 
                size_t name_len = strlen(name);
1342
 
                size_t len = db_len + 1 + name_len + ext_len + 1;
1343
 
                char *path = (char *)xt_malloc_ns(len);
1344
 
                memcpy(path, db, db_len);
1345
 
                memcpy(path + db_len + 1, name, name_len);
1346
 
                memcpy(path + db_len + 1 + name_len, ext, ext_len);
1347
 
                path[db_len] = XT_DIR_CHAR;
1348
 
                path[len - 1] = '\0';
1349
 
                xtBool exists = xt_fs_exists(path);
1350
 
                xt_free_ns(path);
1351
 
                if (exists)
1352
 
                        goto noerror;
1353
 
        }
1354
 
        
1355
 
        /* Create an internal temp table */
1356
 
#ifdef WITH_PARTITION_STORAGE_ENGINE
1357
 
        partition_info *part_info;
1358
 
 
1359
 
        part_info = thd->work_part_info;
1360
 
#endif
1361
 
        if (mysql_create_table_no_lock(thd, db, name, &mylex.create_info, &mylex.alter_info, 1, 0)) 
1362
 
                goto error;
1363
 
#ifdef WITH_PARTITION_STORAGE_ENGINE
1364
 
        thd->work_part_info = part_info;
1365
 
#endif
1366
 
 
1367
 
        noerror:
1368
 
        err = 0;
1369
 
 
1370
 
        error:
1371
 
        lex_end(&mylex);
1372
 
        thd->lex = save_lex;
1373
 
        return err;
1374
 
}
1375
 
 
1376
 
#endif
1377