~ubuntu-branches/ubuntu/trusty/mariadb-5.5/trusty-proposed

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): James Page, Otto Kekäläinen
  • Date: 2014-02-17 16:51:52 UTC
  • mfrom: (2.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20140217165152-k315d3175g865kkx
Tags: 5.5.35-1
[ Otto Kekäläinen ]
* New upstream release, fixing the following security issues:
  - Buffer overflow in client/mysql.cc (Closes: #737597).
    - CVE-2014-0001
  - http://www.oracle.com/technetwork/topics/security/cpujan2014-1972949.html
    - CVE-2013-5891
    - CVE-2013-5908
    - CVE-2014-0386
    - CVE-2014-0393
    - CVE-2014-0401
    - CVE-2014-0402
    - CVE-2014-0412
    - CVE-2014-0420
    - CVE-2014-0437
* Upstream https://mariadb.atlassian.net/browse/MDEV-4902
  fixes compatibility with Bison 3.0 (Closes: #733002)
* Updated Russian debconf translation (Closes: #734426)
* Updated Japanese debconf translation (Closes: #735284)
* Updated French debconf translation (Closes: #736480)
* Renamed SONAME properly (Closes: #732967)

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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
 
 *
20
 
 *  Created by Leslie on 8/27/08.
21
 
 *
22
 
 */
23
 
 
24
 
#include "xt_config.h"
25
 
 
26
 
#ifndef DRIZZLED
27
 
#include <m_ctype.h>
28
 
#include "item.h"
29
 
#include "item_create.h"
30
 
#include "sql_table.h"
31
 
#include "sql_class.h"
32
 
#include "strfunc.h"
33
 
#include "sql_parse.h"
34
 
#include "sql_base.h"
35
 
#include "sql_partition.h" // mem_alloc_error()
36
 
#else
37
 
#include <drizzled/session.h>
38
 
#include <drizzled/server_includes.h>
39
 
#include <drizzled/sql_base.h>
40
 
#include <drizzled/statement/alter_table.h>
41
 
#include <algorithm>
42
 
#include <sstream>
43
 
#endif
44
 
 
45
 
#include "strutil_xt.h"
46
 
#include "ha_pbxt.h"
47
 
#include "discover_xt.h"
48
 
#include "ha_xtsys.h"
49
 
 
50
 
#ifndef DRIZZLED
51
 
#if MYSQL_VERSION_ID >= 50404
52
 
#define DOT_STR(x)                      x.str
53
 
#else
54
 
#define DOT_STR(x)                      x
55
 
#endif
56
 
#endif
57
 
 
58
 
//#ifndef DRIZZLED
59
 
#define LOCK_OPEN_HACK_REQUIRED
60
 
//#endif // DRIZZLED
61
 
 
62
 
#ifdef LOCK_OPEN_HACK_REQUIRED
63
 
#ifdef DRIZZLED
64
 
 
65
 
using namespace drizzled;
66
 
using namespace std;
67
 
 
68
 
#define mysql_create_table_no_lock hacked_mysql_create_table_no_lock
69
 
 
70
 
namespace drizzled {
71
 
 
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);
78
 
}
79
 
 
80
 
static uint32_t build_tmptable_filename(Session* session,
81
 
                                        char *buff, size_t bufflen)
82
 
{
83
 
  uint32_t length;
84
 
  ostringstream path_str, post_tmpdir_str;
85
 
  string tmp;
86
 
 
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();
91
 
 
92
 
  transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
93
 
 
94
 
  path_str << tmp;
95
 
 
96
 
  if (bufflen < path_str.str().length())
97
 
    length= 0;
98
 
  else
99
 
    length= unpack_filename(buff, path_str.str().c_str());
100
 
 
101
 
  return length;
102
 
}
103
 
 
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)
111
 
{
112
 
  char          path[FN_REFLEN];
113
 
  uint32_t          path_length;
114
 
  uint          db_options, key_count;
115
 
  KEY           *key_info_buffer;
116
 
  Cursor        *file;
117
 
  bool          error= true;
118
 
  /* Check for duplicate fields and check type of table to create */
119
 
  if (!alter_info->create_list.elements)
120
 
  {
121
 
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
122
 
               MYF(0));
123
 
    return true;
124
 
  }
125
 
  assert(strcmp(table_name,table_proto->name().c_str())==0);
126
 
  if (check_engine(session, table_name, create_info))
127
 
    return true;
128
 
  db_options= create_info->table_options;
129
 
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
130
 
    db_options|=HA_OPTION_PACK_RECORD;
131
 
  
132
 
  /*if (!(file= create_info->db_type->getCursor((TableShare*) 0, session->mem_root)))
133
 
  {
134
 
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
135
 
    return true;
136
 
  }*/
137
 
 
138
 
  /* PMC - Done to avoid getting the partition handler by mistake! */
139
 
  if (!(file= new (session->mem_root) ha_xtsys(pbxt_hton, NULL)))
140
 
  {
141
 
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
142
 
    return true;
143
 
  }
144
 
 
145
 
  set_table_default_charset(create_info, (char*) db);
146
 
 
147
 
  if (mysql_prepare_create_table(session, 
148
 
                                 create_info,
149
 
                                 table_proto,
150
 
                                 alter_info,
151
 
                                 internal_tmp_table,
152
 
                                 &db_options, file,
153
 
                                 &key_info_buffer, &key_count,
154
 
                                 select_field_count))
155
 
    goto err;
156
 
 
157
 
      /* Check if table exists */
158
 
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
159
 
  {
160
 
    path_length= build_tmptable_filename(session, path, sizeof(path));
161
 
  }
162
 
  else
163
 
  {
164
 
 #ifdef FN_DEVCHAR
165
 
    /* check if the table name contains FN_DEVCHAR when defined */
166
 
    if (strchr(table_name, FN_DEVCHAR))
167
 
    {
168
 
      my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name);
169
 
      return true;
170
 
    }
171
 
#endif
172
 
    path_length= build_table_filename(path, sizeof(path), db, table_name, internal_tmp_table);
173
 
  }
174
 
 
175
 
  /* Check if table already exists */
176
 
  if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
177
 
      session->find_temporary_table(db, table_name))
178
 
  {
179
 
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
180
 
    {
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),
184
 
                          table_name);
185
 
      error= 0;
186
 
      goto err;
187
 
    }
188
 
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
189
 
    goto err;
190
 
  }
191
 
 
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))
194
 
  {
195
 
    if (plugin::StorageEngine::getTableDefinition(*session,
196
 
                                                  path, 
197
 
                                                  db,
198
 
                                                  table_name,
199
 
                                                  internal_tmp_table) == EEXIST)
200
 
    {
201
 
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
202
 
      {
203
 
        error= false;
204
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
205
 
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
206
 
                            table_name);
207
 
        create_info->table_existed= 1;          // Mark that table existed
208
 
      }
209
 
      else
210
 
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
211
 
 
212
 
      goto unlock_and_end;
213
 
    }
214
 
    /*
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.
221
 
 *                                         */
222
 
    if (TableShare::getShare(db, table_name))
223
 
    {
224
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
225
 
      goto unlock_and_end;
226
 
    }
227
 
  }
228
 
  /*
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!
236
 
 *                               */
237
 
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
238
 
  {
239
 
    bool create_if_not_exists =
240
 
      create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
241
 
 
242
 
    char table_path[FN_REFLEN];
243
 
    uint32_t          table_path_length;
244
 
 
245
 
    table_path_length= build_table_filename(table_path, sizeof(table_path),
246
 
                                            db, table_name, false);
247
 
 
248
 
    int retcode= plugin::StorageEngine::getTableDefinition(*session,
249
 
                                                           table_path, 
250
 
                                                           db,
251
 
                                                           table_name,
252
 
                                                           false);
253
 
    switch (retcode)
254
 
    {
255
 
      case ENOENT:
256
 
        /* Normal case, no table exists. we can go and create it */
257
 
        break;
258
 
      case EEXIST:
259
 
        if (create_if_not_exists)
260
 
        {
261
 
          error= false;
262
 
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
263
 
                              ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
264
 
                              table_name);
265
 
          create_info->table_existed= 1;                // Mark that table existed
266
 
          goto unlock_and_end;
267
 
        }
268
 
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
269
 
        goto unlock_and_end;
270
 
      default:
271
 
        my_error(retcode, MYF(0),table_name);
272
 
        goto unlock_and_end;
273
 
    }
274
 
  }
275
 
 
276
 
  session->set_proc_info("creating table");
277
 
  create_info->table_existed= 0;                // Mark that table is created
278
 
 
279
 
  create_info->table_options=db_options;
280
 
 
281
 
  if (rea_create_table(session, path, db, table_name,
282
 
                       table_proto,
283
 
                       create_info, alter_info->create_list,
284
 
                       key_count, key_info_buffer))
285
 
    goto unlock_and_end;
286
 
 
287
 
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
288
 
  {
289
 
    /* Open table and put in temporary table list */
290
 
    if (!(session->open_temporary_table(path, db, table_name, 1, OTM_OPEN)))
291
 
    {
292
 
      (void) session->rm_temporary_table(create_info->db_type, path);
293
 
      goto unlock_and_end;
294
 
    }
295
 
  }
296
 
 
297
 
  /*
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.
303
 
 *                        */
304
 
  if (!internal_tmp_table &&
305
 
      ((!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
306
 
    write_bin_log(session, session->query, session->query_length);
307
 
  error= false;
308
 
unlock_and_end:
309
 
  //pthread_mutex_unlock(&LOCK_open);
310
 
 
311
 
err:
312
 
  session->set_proc_info("After create");
313
 
  delete file;
314
 
  return(error);
315
 
}
316
 
 
317
 
#else // MySQL case
318
 
///////////////////////////////
319
 
/*
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.
324
 
 *
325
 
 * Its almost enough to make you want to cry. :(
326
 
*/
327
 
//-----------------------------
328
 
 
329
 
#ifdef pthread_mutex_lock
330
 
#undef pthread_mutex_lock
331
 
#endif
332
 
 
333
 
#ifdef pthread_mutex_unlock
334
 
#undef pthread_mutex_unlock
335
 
#endif
336
 
 
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)
340
 
 
341
 
#define check_engine(t, n, c) (0)
342
 
#define set_table_default_charset(t, c, d)
343
 
 
344
 
void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
345
 
                                uint32 *max_length, uint32 *tot_length);
346
 
 
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);
350
 
 
351
 
//////////////////////////////////////////////////////////
352
 
////// START OF CUT AND PASTES FROM  sql_table.cc ////////
353
 
//////////////////////////////////////////////////////////
354
 
 
355
 
// sort_keys() cut and pasted directly from sql_table.cc. 
356
 
static int sort_keys(KEY *a, KEY *b)
357
 
{
358
 
  ulong a_flags= a->flags, b_flags= b->flags;
359
 
  
360
 
  if (a_flags & HA_NOSAME)
361
 
  {
362
 
    if (!(b_flags & HA_NOSAME))
363
 
      return -1;
364
 
    if ((a_flags ^ b_flags) & HA_NULL_PART_KEY)
365
 
    {
366
 
      /* Sort NOT NULL keys before other keys */
367
 
      return (a_flags & HA_NULL_PART_KEY) ? 1 : -1;
368
 
    }
369
 
    if (a->name == primary_key_name)
370
 
      return -1;
371
 
    if (b->name == primary_key_name)
372
 
      return 1;
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;
376
 
  }
377
 
  else if (b_flags & HA_NOSAME)
378
 
    return 1;                                   // Prefer b
379
 
 
380
 
  if ((a_flags ^ b_flags) & HA_FULLTEXT)
381
 
  {
382
 
    return (a_flags & HA_FULLTEXT) ? 1 : -1;
383
 
  }
384
 
  /*
385
 
    Prefer original key order.  usable_key_parts contains here
386
 
    the original key position.
387
 
  */
388
 
  return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
389
 
          (a->usable_key_parts > b->usable_key_parts) ? 1 :
390
 
          0);
391
 
}
392
 
 
393
 
// check_if_keyname_exists() cut and pasted directly from sql_table.cc. 
394
 
static bool
395
 
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
396
 
{
397
 
  for (KEY *key=start ; key != end ; key++)
398
 
    if (!my_strcasecmp(system_charset_info,name,key->name))
399
 
      return 1;
400
 
  return 0;
401
 
}
402
 
 
403
 
// make_unique_key_name() cut and pasted directly from sql_table.cc. 
404
 
static char *
405
 
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
406
 
{
407
 
  char buff[MAX_FIELD_NAME],*buff_end;
408
 
 
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);
413
 
 
414
 
  /*
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
417
 
  */
418
 
  for (uint i=2 ; i< 100; i++)
419
 
  {
420
 
    *buff_end= '_';
421
 
    int10_to_str(i, buff_end+1, 10);
422
 
    if (!check_if_keyname_exists(buff,start,end))
423
 
      return sql_strdup(buff);
424
 
  }
425
 
  return (char*) "not_specified";               // Should never happen
426
 
}
427
 
 
428
 
 
429
 
// prepare_blob_field() cut and pasted directly from sql_table.cc. 
430
 
static bool prepare_blob_field(THD *thd, Create_field *sql_field)
431
 
{
432
 
  DBUG_ENTER("prepare_blob_field");
433
 
 
434
 
  if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
435
 
      !(sql_field->flags & BLOB_FLAG))
436
 
  {
437
 
    /* Convert long VARCHAR columns to TEXT or BLOB */
438
 
    char warn_buff[MYSQL_ERRMSG_SIZE];
439
 
 
440
 
    if (sql_field->def || (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
441
 
                                                      MODE_STRICT_ALL_TABLES)))
442
 
    {
443
 
      my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
444
 
               MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
445
 
      DBUG_RETURN(1);
446
 
    }
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,
453
 
                 warn_buff);
454
 
  }
455
 
    
456
 
  if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
457
 
  {
458
 
    if (sql_field->sql_type == MYSQL_TYPE_BLOB)
459
 
    {
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);
463
 
    }
464
 
    sql_field->length= 0;
465
 
  }
466
 
  DBUG_RETURN(0);
467
 
}
468
 
 
469
 
//////////////////////////////
470
 
// mysql_prepare_create_table() cut and pasted directly from sql_table.cc.
471
 
static int
472
 
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
473
 
                           Alter_info *alter_info,
474
 
                           bool tmp_table,
475
 
                           uint *db_options,
476
 
                           handler *file, KEY **key_info_buffer,
477
 
                           uint *key_count, int select_field_count)
478
 
{
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;
483
 
  KEY           *key_info;
484
 
  KEY_PART_INFO *key_part_info;
485
 
  int           timestamps= 0, timestamps_with_niladic= 0;
486
 
  int           field_no,dup_no;
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");
492
 
 
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();
497
 
 
498
 
  for (field_no=0; (sql_field=it++) ; field_no++)
499
 
  {
500
 
    CHARSET_INFO *save_cs;
501
 
 
502
 
    /*
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.
506
 
    */
507
 
    sql_field->length= sql_field->char_length;
508
 
    if (!sql_field->charset)
509
 
      sql_field->charset= create_info->default_table_charset;
510
 
    /*
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.
515
 
    */
516
 
    if (create_info->table_charset && sql_field->charset != &my_charset_bin)
517
 
      sql_field->charset= create_info->table_charset;
518
 
 
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))))
523
 
    {
524
 
      char tmp[64];
525
 
      strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
526
 
              STRING_WITH_LEN("_bin"));
527
 
      my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
528
 
      DBUG_RETURN(TRUE);
529
 
    }
530
 
 
531
 
    /*
532
 
      Convert the default value from client character
533
 
      set into the column character set if necessary.
534
 
    */
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))
541
 
    {
542
 
      /*
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.
551
 
      */
552
 
      sql_field->def= sql_field->def->safe_charset_converter(save_cs);
553
 
 
554
 
      if (sql_field->def == NULL)
555
 
      {
556
 
        /* Could not convert */
557
 
        my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
558
 
        DBUG_RETURN(TRUE);
559
 
      }
560
 
    }
561
 
 
562
 
    if (sql_field->sql_type == MYSQL_TYPE_SET ||
563
 
        sql_field->sql_type == MYSQL_TYPE_ENUM)
564
 
    {
565
 
      uint32 dummy;
566
 
      CHARSET_INFO *cs= sql_field->charset;
567
 
      TYPELIB *interval= sql_field->interval;
568
 
 
569
 
      /*
570
 
        Create typelib from interval_list, and if necessary
571
 
        convert strings from client character set to the
572
 
        column character set.
573
 
      */
574
 
      if (!interval)
575
 
      {
576
 
        /*
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.
580
 
        */
581
 
        interval= sql_field->interval= typelib(thd->mem_root,
582
 
                                               sql_field->interval_list);
583
 
        List_iterator<String> int_it(sql_field->interval_list);
584
 
        String conv, *tmp;
585
 
        char comma_buf[2];
586
 
        int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
587
 
                                          (uchar*) comma_buf + 
588
 
                                          sizeof(comma_buf));
589
 
        DBUG_ASSERT(comma_length > 0);
590
 
        for (uint i= 0; (tmp= int_it++); i++)
591
 
        {
592
 
          uint lengthsp;
593
 
          if (String::needs_conversion(tmp->length(), tmp->charset(),
594
 
                                       cs, &dummy))
595
 
          {
596
 
            uint cnv_errs;
597
 
            conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
598
 
            interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
599
 
                                                  conv.length());
600
 
            interval->type_lengths[i]= conv.length();
601
 
          }
602
 
 
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)
609
 
          {
610
 
            if (cs->coll->instr(cs, interval->type_names[i], 
611
 
                                interval->type_lengths[i], 
612
 
                                comma_buf, comma_length, NULL, 0))
613
 
            {
614
 
              my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr());
615
 
              DBUG_RETURN(TRUE);
616
 
            }
617
 
          }
618
 
        }
619
 
        sql_field->interval_list.empty(); // Don't need interval_list anymore
620
 
      }
621
 
 
622
 
      if (sql_field->sql_type == MYSQL_TYPE_SET)
623
 
      {
624
 
        uint32 field_length;
625
 
        if (sql_field->def != NULL)
626
 
        {
627
 
          char *not_used;
628
 
          uint not_used2;
629
 
          bool not_found= 0;
630
 
          String str, *def= sql_field->def->val_str(&str);
631
 
          if (def == NULL) /* SQL "NULL" maps to NULL */
632
 
          {
633
 
            if ((sql_field->flags & NOT_NULL_FLAG) != 0)
634
 
            {
635
 
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
636
 
              DBUG_RETURN(TRUE);
637
 
            }
638
 
 
639
 
            /* else, NULL is an allowed value */
640
 
            (void) find_set(interval, NULL, 0,
641
 
                            cs, &not_used, &not_used2, &not_found);
642
 
          }
643
 
          else /* not NULL */
644
 
          {
645
 
            (void) find_set(interval, def->ptr(), def->length(),
646
 
                            cs, &not_used, &not_used2, &not_found);
647
 
          }
648
 
 
649
 
          if (not_found)
650
 
          {
651
 
            my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
652
 
            DBUG_RETURN(TRUE);
653
 
          }
654
 
        }
655
 
        calculate_interval_lengths(cs, interval, &dummy, &field_length);
656
 
        sql_field->length= field_length + (interval->count - 1);
657
 
      }
658
 
      else  /* MYSQL_TYPE_ENUM */
659
 
      {
660
 
        uint32 field_length;
661
 
        DBUG_ASSERT(sql_field->sql_type == MYSQL_TYPE_ENUM);
662
 
        if (sql_field->def != NULL)
663
 
        {
664
 
          String str, *def= sql_field->def->val_str(&str);
665
 
          if (def == NULL) /* SQL "NULL" maps to NULL */
666
 
          {
667
 
            if ((sql_field->flags & NOT_NULL_FLAG) != 0)
668
 
            {
669
 
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
670
 
              DBUG_RETURN(TRUE);
671
 
            }
672
 
 
673
 
            /* else, the defaults yield the correct length for NULLs. */
674
 
          } 
675
 
          else /* not NULL */
676
 
          {
677
 
            def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
678
 
            if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
679
 
            {
680
 
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
681
 
              DBUG_RETURN(TRUE);
682
 
            }
683
 
          }
684
 
        }
685
 
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
686
 
        sql_field->length= field_length;
687
 
      }
688
 
      set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
689
 
    }
690
 
 
691
 
    if (sql_field->sql_type == MYSQL_TYPE_BIT)
692
 
    { 
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;
696
 
      else
697
 
        sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
698
 
    }
699
 
 
700
 
    sql_field->create_length_to_internal_length();
701
 
    if (prepare_blob_field(thd, sql_field))
702
 
      DBUG_RETURN(TRUE);
703
 
 
704
 
    if (!(sql_field->flags & NOT_NULL_FLAG))
705
 
      null_fields++;
706
 
 
707
 
    if (check_column_name(sql_field->field_name))
708
 
    {
709
 
      my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
710
 
      DBUG_RETURN(TRUE);
711
 
    }
712
 
 
713
 
    /* Check if we have used the same field name before */
714
 
    for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
715
 
    {
716
 
      if (my_strcasecmp(system_charset_info,
717
 
                        sql_field->field_name,
718
 
                        dup_field->field_name) == 0)
719
 
      {
720
 
        /*
721
 
          If this was a CREATE ... SELECT statement, accept a field
722
 
          redefinition if we are changing a field in the SELECT part
723
 
        */
724
 
        if (field_no < select_field_pos || dup_no >= select_field_pos)
725
 
        {
726
 
          my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
727
 
          DBUG_RETURN(TRUE);
728
 
        }
729
 
        else
730
 
        {
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 ?
735
 
                                         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;
743
 
          /* 
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.
747
 
          */
748
 
          if (!(sql_field->flags & NOT_NULL_FLAG))
749
 
            null_fields--;
750
 
          sql_field->flags=             dup_field->flags;
751
 
          sql_field->interval=          dup_field->interval;
752
 
          it2.remove();                 // Remove first (create) definition
753
 
          select_field_pos--;
754
 
          break;
755
 
        }
756
 
      }
757
 
    }
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;
763
 
    it2.rewind();
764
 
  }
765
 
 
766
 
  /* record_offset will be increased with 'length-of-null-bits' later */
767
 
  record_offset= 0;
768
 
  null_fields+= total_uneven_bit_length;
769
 
 
770
 
  it.rewind();
771
 
  while ((sql_field=it++))
772
 
  {
773
 
    DBUG_ASSERT(sql_field->charset != 0);
774
 
 
775
 
    if (prepare_create_field(sql_field, &blob_columns, 
776
 
                             &timestamps, &timestamps_with_niladic,
777
 
                             file->ha_table_flags()))
778
 
      DBUG_RETURN(TRUE);
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)
783
 
      auto_increment++;
784
 
    record_offset+= sql_field->pack_length;
785
 
  }
786
 
  if (timestamps_with_niladic > 1)
787
 
  {
788
 
    my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
789
 
               ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
790
 
    DBUG_RETURN(TRUE);
791
 
  }
792
 
  if (auto_increment > 1)
793
 
  {
794
 
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
795
 
    DBUG_RETURN(TRUE);
796
 
  }
797
 
  if (auto_increment &&
798
 
      (file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
799
 
  {
800
 
    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
801
 
               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
802
 
    DBUG_RETURN(TRUE);
803
 
  }
804
 
 
805
 
  if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
806
 
  {
807
 
    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
808
 
               MYF(0));
809
 
    DBUG_RETURN(TRUE);
810
 
  }
811
 
 
812
 
  /* Create keys */
813
 
 
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;
818
 
  Key *key, *key2;
819
 
  uint tmp, key_number;
820
 
  /* special marker for keys to be ignored */
821
 
  static char ignore_key[1];
822
 
 
823
 
  /* Calculate number of key segements */
824
 
  *key_count= 0;
825
 
  
826
 
  while ((key=key_iterator++))
827
 
  {
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)
832
 
    {
833
 
      fk_key_count++;
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)
837
 
      {
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));
841
 
        DBUG_RETURN(TRUE);
842
 
      }
843
 
      continue;
844
 
    }
845
 
    (*key_count)++;
846
 
    tmp=file->max_key_parts();
847
 
    if (key->columns.elements > tmp)
848
 
    {
849
 
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
850
 
      DBUG_RETURN(TRUE);
851
 
    }
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))
856
 
    {
857
 
      my_error(ER_TOO_LONG_IDENT, MYF(0), key->DOT_STR(name));
858
 
      DBUG_RETURN(TRUE);
859
 
    }
860
 
    key_iterator2.rewind ();
861
 
    if (key->type != Key::FOREIGN_KEY)
862
 
    {
863
 
      while ((key2 = key_iterator2++) != key)
864
 
      {
865
 
        /*
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.
869
 
        */
870
 
        if ((key2->type != Key::FOREIGN_KEY &&
871
 
             key2->DOT_STR(name) != ignore_key &&
872
 
             !foreign_key_prefix(key, key2)))
873
 
        {
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;
880
 
          else
881
 
          {
882
 
            key2->DOT_STR(name)= ignore_key;
883
 
            key_parts-= key2->columns.elements;
884
 
            (*key_count)--;
885
 
          }
886
 
          break;
887
 
        }
888
 
      }
889
 
    }
890
 
    if (key->DOT_STR(name) != ignore_key)
891
 
      key_parts+=key->columns.elements;
892
 
    else
893
 
      (*key_count)--;
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))
896
 
    {
897
 
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->DOT_STR(name));
898
 
      DBUG_RETURN(TRUE);
899
 
    }
900
 
  }
901
 
  tmp=file->max_keys();
902
 
  if (*key_count > tmp)
903
 
  {
904
 
    my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
905
 
    DBUG_RETURN(TRUE);
906
 
  }
907
 
 
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
912
 
 
913
 
  key_iterator.rewind();
914
 
  key_number=0;
915
 
  for (; (key=key_iterator++) ; key_number++)
916
 
  {
917
 
    uint key_length=0;
918
 
    Key_part_spec *column;
919
 
 
920
 
    if (key->DOT_STR(name) == ignore_key)
921
 
    {
922
 
      /* ignore redundant keys */
923
 
      do
924
 
        key=key_iterator++;
925
 
      while (key && key->DOT_STR(name) == ignore_key);
926
 
      if (!key)
927
 
        break;
928
 
    }
929
 
 
930
 
    switch (key->type) {
931
 
    case Key::MULTIPLE:
932
 
        key_info->flags= 0;
933
 
        break;
934
 
    case Key::FULLTEXT:
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;
938
 
        else
939
 
          key_info->parser_name= 0;
940
 
        break;
941
 
    case Key::SPATIAL:
942
 
#ifdef HAVE_SPATIAL
943
 
        key_info->flags= HA_SPATIAL;
944
 
        break;
945
 
#else
946
 
        my_error(ER_FEATURE_DISABLED, MYF(0),
947
 
                 sym_group_geom.name, sym_group_geom.needed_define);
948
 
        DBUG_RETURN(TRUE);
949
 
#endif
950
 
    case Key::FOREIGN_KEY:
951
 
      key_number--;                             // Skip this key
952
 
      continue;
953
 
    default:
954
 
      key_info->flags = HA_NOSAME;
955
 
      break;
956
 
    }
957
 
    if (key->generated)
958
 
      key_info->flags|= HA_GENERATED_KEY;
959
 
 
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;
964
 
 
965
 
    if (key->type == Key::FULLTEXT)
966
 
    {
967
 
      if (!(file->ha_table_flags() & HA_CAN_FULLTEXT))
968
 
      {
969
 
        my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT),
970
 
                   MYF(0));
971
 
        DBUG_RETURN(TRUE);
972
 
      }
973
 
    }
974
 
    /*
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:
980
 
    */
981
 
 
982
 
    /* TODO: Add proper checks if handler supports key_type and algorithm */
983
 
    if (key_info->flags & HA_SPATIAL)
984
 
    {
985
 
      if (!(file->ha_table_flags() & HA_CAN_RTREEKEYS))
986
 
      {
987
 
        my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS),
988
 
                   MYF(0));
989
 
        DBUG_RETURN(TRUE);
990
 
      }
991
 
      if (key_info->key_parts != 1)
992
 
      {
993
 
        my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
994
 
        DBUG_RETURN(TRUE);
995
 
      }
996
 
    }
997
 
    else if (key_info->algorithm == HA_KEY_ALG_RTREE)
998
 
    {
999
 
#ifdef HAVE_RTREE_KEYS
1000
 
      if ((key_info->key_parts & 1) == 1)
1001
 
      {
1002
 
        my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX");
1003
 
        DBUG_RETURN(TRUE);
1004
 
      }
1005
 
      /* TODO: To be deleted */
1006
 
      my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX");
1007
 
      DBUG_RETURN(TRUE);
1008
 
#else
1009
 
      my_error(ER_FEATURE_DISABLED, MYF(0),
1010
 
               sym_group_rtree.name, sym_group_rtree.needed_define);
1011
 
      DBUG_RETURN(TRUE);
1012
 
#endif
1013
 
    }
1014
 
 
1015
 
    /* Take block size from key part or table part */
1016
 
    /*
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
1019
 
    */
1020
 
    key_info->block_size= (key->key_create_info.block_size ?
1021
 
                           key->key_create_info.block_size :
1022
 
                           create_info->key_block_size);
1023
 
 
1024
 
    if (key_info->block_size)
1025
 
      key_info->flags|= HA_USES_BLOCK_SIZE;
1026
 
 
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++)
1030
 
    {
1031
 
      uint length;
1032
 
      Key_part_spec *dup_column;
1033
 
 
1034
 
      it.rewind();
1035
 
      field=0;
1036
 
      while ((sql_field=it++) &&
1037
 
             my_strcasecmp(system_charset_info,
1038
 
                           column->DOT_STR(field_name),
1039
 
                           sql_field->field_name))
1040
 
        field++;
1041
 
      if (!sql_field)
1042
 
      {
1043
 
        my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
1044
 
        DBUG_RETURN(TRUE);
1045
 
      }
1046
 
      while ((dup_column= cols2++) != column)
1047
 
      {
1048
 
        if (!my_strcasecmp(system_charset_info,
1049
 
                           column->DOT_STR(field_name), dup_column->DOT_STR(field_name)))
1050
 
        {
1051
 
          my_printf_error(ER_DUP_FIELDNAME,
1052
 
                          ER(ER_DUP_FIELDNAME),MYF(0),
1053
 
                          column->field_name);
1054
 
          DBUG_RETURN(TRUE);
1055
 
        }
1056
 
      }
1057
 
      cols2.rewind();
1058
 
      if (key->type == Key::FULLTEXT)
1059
 
      {
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))
1066
 
        {
1067
 
            my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name);
1068
 
            DBUG_RETURN(-1);
1069
 
        }
1070
 
        ft_key_charset=sql_field->charset;
1071
 
        /*
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).
1077
 
        */
1078
 
        column->length=test(f_is_blob(sql_field->pack_flag));
1079
 
      }
1080
 
      else
1081
 
      {
1082
 
        column->length*= sql_field->charset->mbmaxlen;
1083
 
 
1084
 
        if (key->type == Key::SPATIAL && column->length)
1085
 
        {
1086
 
          my_error(ER_WRONG_SUB_KEY, MYF(0));
1087
 
          DBUG_RETURN(TRUE);
1088
 
        }
1089
 
 
1090
 
        if (f_is_blob(sql_field->pack_flag) ||
1091
 
            (f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
1092
 
        {
1093
 
          if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
1094
 
          {
1095
 
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name);
1096
 
            DBUG_RETURN(TRUE);
1097
 
          }
1098
 
          if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
1099
 
              Field::GEOM_POINT)
1100
 
            column->length= 25;
1101
 
          if (!column->length)
1102
 
          {
1103
 
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name);
1104
 
            DBUG_RETURN(TRUE);
1105
 
          }
1106
 
        }
1107
 
#ifdef HAVE_SPATIAL
1108
 
        if (key->type == Key::SPATIAL)
1109
 
        {
1110
 
          if (!column->length)
1111
 
          {
1112
 
            /*
1113
 
              4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
1114
 
              Lately we'll extend this code to support more dimensions
1115
 
            */
1116
 
            column->length= 4*sizeof(double);
1117
 
          }
1118
 
        }
1119
 
#endif
1120
 
        if (!(sql_field->flags & NOT_NULL_FLAG))
1121
 
        {
1122
 
          if (key->type == Key::PRIMARY)
1123
 
          {
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;
1127
 
            null_fields--;
1128
 
          }
1129
 
          else
1130
 
          {
1131
 
            key_info->flags|= HA_NULL_PART_KEY;
1132
 
            if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
1133
 
            {
1134
 
              my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name);
1135
 
              DBUG_RETURN(TRUE);
1136
 
            }
1137
 
            if (key->type == Key::SPATIAL)
1138
 
            {
1139
 
              my_message(ER_SPATIAL_CANT_HAVE_NULL,
1140
 
                         ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
1141
 
              DBUG_RETURN(TRUE);
1142
 
            }
1143
 
          }
1144
 
        }
1145
 
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1146
 
        {
1147
 
          if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
1148
 
            auto_increment--;                   // Field is used
1149
 
        }
1150
 
      }
1151
 
 
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;
1156
 
 
1157
 
      if (column->length)
1158
 
      {
1159
 
        if (f_is_blob(sql_field->pack_flag))
1160
 
        {
1161
 
          if ((length=column->length) > max_key_length ||
1162
 
              length > file->max_key_part_length())
1163
 
          {
1164
 
            length=min(max_key_length, file->max_key_part_length());
1165
 
            if (key->type == Key::MULTIPLE)
1166
 
            {
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),
1170
 
                          length);
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;
1175
 
            }
1176
 
            else
1177
 
            {
1178
 
              my_error(ER_TOO_LONG_KEY,MYF(0),length);
1179
 
              DBUG_RETURN(TRUE);
1180
 
            }
1181
 
          }
1182
 
        }
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)))
1190
 
        {
1191
 
          my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1192
 
          DBUG_RETURN(TRUE);
1193
 
        }
1194
 
        else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
1195
 
          length=column->length;
1196
 
      }
1197
 
      else if (length == 0)
1198
 
      {
1199
 
        my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name);
1200
 
          DBUG_RETURN(TRUE);
1201
 
      }
1202
 
      if (length > file->max_key_part_length() && key->type != Key::FULLTEXT)
1203
 
      {
1204
 
        length= file->max_key_part_length();
1205
 
        if (key->type == Key::MULTIPLE)
1206
 
        {
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),
1210
 
                      length);
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;
1215
 
        }
1216
 
        else
1217
 
        {
1218
 
          my_error(ER_TOO_LONG_KEY,MYF(0),length);
1219
 
          DBUG_RETURN(TRUE);
1220
 
        }
1221
 
      }
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)))
1229
 
      {
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;
1233
 
        else
1234
 
          key_info->flags|= HA_PACK_KEY;
1235
 
      }
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;
1239
 
 
1240
 
      key_length+=length;
1241
 
      key_part_info++;
1242
 
 
1243
 
      /* Create the key name based on the first column (if not given) */
1244
 
      if (column_nr == 0)
1245
 
      {
1246
 
        if (key->type == Key::PRIMARY)
1247
 
        {
1248
 
          if (primary_key)
1249
 
          {
1250
 
            my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
1251
 
                       MYF(0));
1252
 
            DBUG_RETURN(TRUE);
1253
 
          }
1254
 
          key_name=primary_key_name;
1255
 
          primary_key=1;
1256
 
        }
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))
1261
 
        {
1262
 
          my_error(ER_DUP_KEYNAME, MYF(0), key_name);
1263
 
          DBUG_RETURN(TRUE);
1264
 
        }
1265
 
        key_info->name=(char*) key_name;
1266
 
      }
1267
 
    }
1268
 
    if (!key_info->name || check_column_name(key_info->name))
1269
 
    {
1270
 
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1271
 
      DBUG_RETURN(TRUE);
1272
 
    }
1273
 
    if (!(key_info->flags & HA_NULL_PART_KEY))
1274
 
      unique_key=1;
1275
 
    key_info->key_length=(uint16) key_length;
1276
 
    if (key_length > max_key_length && key->type != Key::FULLTEXT)
1277
 
    {
1278
 
      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1279
 
      DBUG_RETURN(TRUE);
1280
 
    }
1281
 
    key_info++;
1282
 
  }
1283
 
  if (!unique_key && !primary_key &&
1284
 
      (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1285
 
  {
1286
 
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1287
 
    DBUG_RETURN(TRUE);
1288
 
  }
1289
 
  if (auto_increment > 0)
1290
 
  {
1291
 
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1292
 
    DBUG_RETURN(TRUE);
1293
 
  }
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;
1298
 
 
1299
 
  /* Check fields. */
1300
 
  it.rewind();
1301
 
  while ((sql_field=it++))
1302
 
  {
1303
 
    Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1304
 
 
1305
 
    if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
1306
 
        !sql_field->def &&
1307
 
        sql_field->sql_type == MYSQL_TYPE_TIMESTAMP &&
1308
 
        (sql_field->flags & NOT_NULL_FLAG) &&
1309
 
        (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1310
 
    {
1311
 
      /*
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.
1318
 
 
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'.
1323
 
      */
1324
 
 
1325
 
      my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
1326
 
      DBUG_RETURN(TRUE);
1327
 
    }
1328
 
  }
1329
 
 
1330
 
  DBUG_RETURN(FALSE);
1331
 
}
1332
 
 
1333
 
//////////////////////////////
1334
 
// mysql_create_table_no_lock() cut and pasted directly from sql_table.cc. (I did make is static after copying it.)
1335
 
 
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)
1342
 
{
1343
 
  char                  path[FN_REFLEN];
1344
 
  uint          path_length;
1345
 
  const char    *alias;
1346
 
  uint                  db_options, key_count;
1347
 
  KEY                   *key_info_buffer;
1348
 
  handler               *file;
1349
 
  bool                  error= TRUE;
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));
1353
 
 
1354
 
 
1355
 
  /* Check for duplicate fields and check type of table to create */
1356
 
  if (!alter_info->create_list.elements)
1357
 
  {
1358
 
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1359
 
               MYF(0));
1360
 
    DBUG_RETURN(TRUE);
1361
 
  }
1362
 
  if (check_engine(thd, table_name, create_info))
1363
 
    DBUG_RETURN(TRUE);
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);
1368
 
 
1369
 
  /* PMC - Done to avoid getting the partition handler by mistake! */
1370
 
  if (!(file= new (thd->mem_root) ha_xtsys(pbxt_hton, NULL)))
1371
 
  {
1372
 
    mem_alloc_error(sizeof(handler));
1373
 
    DBUG_RETURN(TRUE);
1374
 
  }
1375
 
 
1376
 
  set_table_default_charset(thd, create_info, (char*) db);
1377
 
 
1378
 
  if (mysql_prepare_create_table(thd, create_info, alter_info,
1379
 
                                 internal_tmp_table,
1380
 
                                 &db_options, file,
1381
 
                                 &key_info_buffer, &key_count,
1382
 
                                 select_field_count))
1383
 
    goto err;
1384
 
 
1385
 
      /* Check if table exists */
1386
 
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1387
 
  {
1388
 
    path_length= build_tmptable_filename(thd, path, sizeof(path));
1389
 
    create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
1390
 
  }
1391
 
  else  
1392
 
  {
1393
 
 #ifdef FN_DEVCHAR
1394
 
    /* check if the table name contains FN_DEVCHAR when defined */
1395
 
    if (strchr(alias, FN_DEVCHAR))
1396
 
    {
1397
 
      my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
1398
 
      DBUG_RETURN(TRUE);
1399
 
    }
1400
 
#endif
1401
 
    path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
1402
 
                                      internal_tmp_table ? FN_IS_TMP : 0);
1403
 
  }
1404
 
 
1405
 
  /* Check if table already exists */
1406
 
  if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1407
 
      find_temporary_table(thd, db, table_name))
1408
 
  {
1409
 
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1410
 
    {
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),
1414
 
                          alias);
1415
 
      error= 0;
1416
 
      goto err;
1417
 
    }
1418
 
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
1419
 
    goto err;
1420
 
  }
1421
 
 
1422
 
  pthread_mutex_lock(&LOCK_open);
1423
 
  if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1424
 
  {
1425
 
    if (!access(path,F_OK))
1426
 
    {
1427
 
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1428
 
        goto warn;
1429
 
      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1430
 
      goto unlock_and_end;
1431
 
    }
1432
 
    /*
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.
1439
 
    */
1440
 
    if (get_cached_table_share(db, alias))
1441
 
    {
1442
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1443
 
      goto unlock_and_end;
1444
 
    }
1445
 
  }
1446
 
 
1447
 
  /*
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!
1455
 
  */
1456
 
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1457
 
  {
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));
1462
 
    switch (retcode)
1463
 
    {
1464
 
      case HA_ERR_NO_SUCH_TABLE:
1465
 
        /* Normal case, no table exists. we can go and create it */
1466
 
        break;
1467
 
      case HA_ERR_TABLE_EXIST:
1468
 
        DBUG_PRINT("info", ("Table existed in handler"));
1469
 
 
1470
 
        if (create_if_not_exists)
1471
 
          goto warn;
1472
 
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1473
 
        goto unlock_and_end;
1474
 
        break;
1475
 
      default:
1476
 
        DBUG_PRINT("info", ("error: %u from storage engine", retcode));
1477
 
        my_error(retcode, MYF(0),table_name);
1478
 
        goto unlock_and_end;
1479
 
    }
1480
 
  }
1481
 
 
1482
 
  thd_proc_info(thd, "creating table");
1483
 
  //create_info->table_existed= 0;              // Mark that table is created
1484
 
 
1485
 
  create_info->table_options=db_options;
1486
 
 
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;
1492
 
 
1493
 
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1494
 
  {
1495
 
    /* Open table and put in temporary table list */
1496
 
    TABLE *table= open_table_uncached(thd, path, db, table_name, TRUE);
1497
 
    if (!table)
1498
 
    {
1499
 
      (void) rm_temporary_table(create_info->db_type, path);
1500
 
      goto unlock_and_end;
1501
 
    }
1502
 
    thd->thread_specific_used= TRUE;
1503
 
  }
1504
 
 
1505
 
  /*
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.
1511
 
   */
1512
 
  /* PBXT 1.0.09e
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*'
1516
 
   * 
1517
 
   * And secondly, we should no write the BINLOG anyway because this is
1518
 
   * an internal PBXT system table.
1519
 
   *
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);
1526
 
   */
1527
 
  error= FALSE;
1528
 
unlock_and_end:
1529
 
  pthread_mutex_unlock(&LOCK_open);
1530
 
 
1531
 
err:
1532
 
  thd_proc_info(thd, "After create");
1533
 
  delete file;
1534
 
  DBUG_RETURN(error);
1535
 
 
1536
 
warn:
1537
 
  error= FALSE;
1538
 
  push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1539
 
                      ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1540
 
                      alias);
1541
 
  //create_info->table_existed= 1;              // Mark that table existed
1542
 
  goto unlock_and_end;
1543
 
}
1544
 
 
1545
 
////////////////////////////////////////////////////////
1546
 
////// END OF CUT AND PASTES FROM  sql_table.cc ////////
1547
 
////////////////////////////////////////////////////////
1548
 
 
1549
 
#endif // DRIZZLED
1550
 
#endif // LOCK_OPEN_HACK_REQUIRED
1551
 
 
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)
1554
 
{
1555
 
#ifdef DRIZZLED
1556
 
#define MYLEX_CREATE_INFO create_info
1557
 
#else
1558
 
#define MYLEX_CREATE_INFO mylex.create_info 
1559
 
#endif
1560
 
 
1561
 
#ifdef DRIZZLED
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;
1566
 
 
1567
 
        static const char *ext = ".dfe";
1568
 
        static const int ext_len = 4;
1569
 
 
1570
 
        table_proto.mutable_engine()->mutable_name()->assign("PBXT");
1571
 
#else
1572
 
        static const char *ext = ".frm";
1573
 
        static const int ext_len = 4;
1574
 
#endif
1575
 
        int err = 1;
1576
 
        char field_length_buffer[12], *field_length_ptr;
1577
 
        LEX  *save_lex= thd->lex, mylex;
1578
 
 
1579
 
        memset(&MYLEX_CREATE_INFO, 0, sizeof(HA_CREATE_INFO));
1580
 
 
1581
 
        thd->lex = &mylex;
1582
 
        lex_start(thd);
1583
 
#ifdef DRIZZLED
1584
 
        mylex.statement = stmt;
1585
 
#endif
1586
 
        
1587
 
        /* setup the create info */
1588
 
        MYLEX_CREATE_INFO.db_type = hton;
1589
 
 
1590
 
#ifndef DRIZZLED 
1591
 
        mylex.create_info.frm_only = 1;
1592
 
#endif
1593
 
        MYLEX_CREATE_INFO.default_table_charset = system_charset_info;
1594
 
        
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);
1600
 
                 
1601
 
                 comment.str = (char*)(info->comment);
1602
 
                 comment.length = strlen(info->comment);
1603
 
                                        
1604
 
                 if (info->field_length) {
1605
 
                        sprintf(field_length_buffer, "%d", info->field_length);
1606
 
                        field_length_ptr = field_length_buffer;
1607
 
                 } else 
1608
 
                        field_length_ptr = NULL;
1609
 
 
1610
 
#ifdef DRIZZLED
1611
 
                if (add_field_to_list(thd, &field_name, info->field_type, field_length_ptr, info->field_decimal_length,
1612
 
                        info->field_flags,
1613
 
            COLUMN_FORMAT_TYPE_FIXED,
1614
 
                    NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
1615
 
            NULL /*interval_list*/, info->field_charset))
1616
 
#else
1617
 
                if (add_field_to_list(thd, &field_name, info->field_type, field_length_ptr, info->field_decimal_length,
1618
 
                        info->field_flags,
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 */
1623
 
#endif
1624
 
                       )) 
1625
 
#endif
1626
 
                        goto error;
1627
 
 
1628
 
 
1629
 
                info++;
1630
 
        }
1631
 
 
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);
1643
 
                xt_free_ns(path);
1644
 
                if (exists)
1645
 
                        goto noerror;
1646
 
        }
1647
 
        
1648
 
        /* Create an internal temp table */
1649
 
#ifdef DRIZZLED
1650
 
    table_proto.set_name(name);
1651
 
    table_proto.set_type(drizzled::message::Table::STANDARD);
1652
 
 
1653
 
        if (mysql_create_table_no_lock(thd, db, name, &create_info, &table_proto, &stmt->alter_info, 1, 0)) 
1654
 
                goto error;
1655
 
#else
1656
 
#ifdef WITH_PARTITION_STORAGE_ENGINE
1657
 
        partition_info *part_info;
1658
 
 
1659
 
        part_info = thd->work_part_info;
1660
 
        thd->work_part_info = NULL;
1661
 
#endif
1662
 
        if (mysql_create_table_no_lock(thd, db, name, &mylex.create_info, &mylex.alter_info, 1, 0)) 
1663
 
                goto error;
1664
 
#ifdef WITH_PARTITION_STORAGE_ENGINE
1665
 
        thd->work_part_info = part_info;
1666
 
#endif
1667
 
#endif
1668
 
 
1669
 
        noerror:
1670
 
        err = 0;
1671
 
 
1672
 
        error:
1673
 
        lex_end(&mylex);
1674
 
        thd->lex = save_lex;
1675
 
        return err;
1676
 
}
1677