~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2006 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
17
/* Some general useful functions */
18
19
#include "mysql_priv.h"
20
#include <m_ctype.h>
21
#include "my_md5.h"
22
23
/* INFORMATION_SCHEMA name */
24
LEX_STRING INFORMATION_SCHEMA_NAME= {C_STRING_WITH_LEN("information_schema")};
25
26
/* MYSQL_SCHEMA name */
27
LEX_STRING MYSQL_SCHEMA_NAME= {C_STRING_WITH_LEN("mysql")};
28
29
/* Functions defined in this file */
30
31
void open_table_error(TABLE_SHARE *share, int error, int db_errno,
32
                      myf errortype, int errarg);
33
static int open_binary_frm(THD *thd, TABLE_SHARE *share,
34
                           uchar *head, File file);
35
static void fix_type_pointers(const char ***array, TYPELIB *point_to_type,
36
			      uint types, char **names);
37
static uint find_field(Field **fields, uchar *record, uint start, uint length);
38
39
inline bool is_system_table_name(const char *name, uint length);
40
41
/**************************************************************************
42
  Object_creation_ctx implementation.
43
**************************************************************************/
44
45
Object_creation_ctx *Object_creation_ctx::set_n_backup(THD *thd)
46
{
47
  Object_creation_ctx *backup_ctx;
48
  DBUG_ENTER("Object_creation_ctx::set_n_backup");
49
50
  backup_ctx= create_backup_ctx(thd);
51
  change_env(thd);
52
53
  DBUG_RETURN(backup_ctx);
54
}
55
56
void Object_creation_ctx::restore_env(THD *thd, Object_creation_ctx *backup_ctx)
57
{
58
  if (!backup_ctx)
59
    return;
60
61
  backup_ctx->change_env(thd);
62
63
  delete backup_ctx;
64
}
65
66
/**************************************************************************
67
  Default_object_creation_ctx implementation.
68
**************************************************************************/
69
70
Default_object_creation_ctx::Default_object_creation_ctx(THD *thd)
71
  : m_client_cs(thd->variables.character_set_client),
72
    m_connection_cl(thd->variables.collation_connection)
73
{ }
74
75
Default_object_creation_ctx::Default_object_creation_ctx(
76
  CHARSET_INFO *client_cs, CHARSET_INFO *connection_cl)
77
  : m_client_cs(client_cs),
78
    m_connection_cl(connection_cl)
79
{ }
80
81
Object_creation_ctx *
82
Default_object_creation_ctx::create_backup_ctx(THD *thd) const
83
{
84
  return new Default_object_creation_ctx(thd);
85
}
86
87
void Default_object_creation_ctx::change_env(THD *thd) const
88
{
89
  thd->variables.character_set_client= m_client_cs;
90
  thd->variables.collation_connection= m_connection_cl;
91
92
  thd->update_charset();
93
}
94
95
/*************************************************************************/
96
97
/* Get column name from column hash */
98
99
static uchar *get_field_name(Field **buff, size_t *length,
100
                             my_bool not_used __attribute__((unused)))
101
{
102
  *length= (uint) strlen((*buff)->field_name);
103
  return (uchar*) (*buff)->field_name;
104
}
105
106
107
/*
108
  Returns pointer to '.frm' extension of the file name.
109
110
  SYNOPSIS
111
    fn_rext()
112
    name       file name
113
114
  DESCRIPTION
115
    Checks file name part starting with the rightmost '.' character,
116
    and returns it if it is equal to '.frm'. 
117
118
  TODO
119
    It is a good idea to get rid of this function modifying the code
120
    to garantee that the functions presently calling fn_rext() always
121
    get arguments in the same format: either with '.frm' or without '.frm'.
122
123
  RETURN VALUES
124
    Pointer to the '.frm' extension. If there is no extension,
125
    or extension is not '.frm', pointer at the end of file name.
126
*/
127
128
char *fn_rext(char *name)
129
{
130
  char *res= strrchr(name, '.');
131
  if (res && !strcmp(res, reg_ext))
132
    return res;
133
  return name + strlen(name);
134
}
135
136
TABLE_CATEGORY get_table_category(const LEX_STRING *db, const LEX_STRING *name)
137
{
138
  DBUG_ASSERT(db != NULL);
139
  DBUG_ASSERT(name != NULL);
140
141
  if ((db->length == INFORMATION_SCHEMA_NAME.length) &&
142
      (my_strcasecmp(system_charset_info,
143
                    INFORMATION_SCHEMA_NAME.str,
144
                    db->str) == 0))
145
  {
146
    return TABLE_CATEGORY_INFORMATION;
147
  }
148
149
  if ((db->length == MYSQL_SCHEMA_NAME.length) &&
150
      (my_strcasecmp(system_charset_info,
151
                    MYSQL_SCHEMA_NAME.str,
152
                    db->str) == 0))
153
  {
154
    if (is_system_table_name(name->str, name->length))
155
    {
156
      return TABLE_CATEGORY_SYSTEM;
157
    }
158
  }
159
160
  return TABLE_CATEGORY_USER;
161
}
162
163
164
/*
165
  Allocate a setup TABLE_SHARE structure
166
167
  SYNOPSIS
168
    alloc_table_share()
169
    TABLE_LIST		Take database and table name from there
170
    key			Table cache key (db \0 table_name \0...)
171
    key_length		Length of key
172
173
  RETURN
174
    0  Error (out of memory)
175
    #  Share
176
*/
177
178
TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, char *key,
179
                               uint key_length)
180
{
181
  MEM_ROOT mem_root;
182
  TABLE_SHARE *share;
183
  char *key_buff, *path_buff;
184
  char path[FN_REFLEN];
185
  uint path_length;
186
  DBUG_ENTER("alloc_table_share");
187
  DBUG_PRINT("enter", ("table: '%s'.'%s'",
188
                       table_list->db, table_list->table_name));
189
190
  path_length= build_table_filename(path, sizeof(path) - 1,
191
                                    table_list->db,
192
                                    table_list->table_name, "", 0);
193
  init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
194
  if (multi_alloc_root(&mem_root,
195
                       &share, sizeof(*share),
196
                       &key_buff, key_length,
197
                       &path_buff, path_length + 1,
198
                       NULL))
199
  {
200
    bzero((char*) share, sizeof(*share));
201
202
    share->set_table_cache_key(key_buff, key, key_length);
203
204
    share->path.str= path_buff;
205
    share->path.length= path_length;
206
    strmov(share->path.str, path);
207
    share->normalized_path.str=    share->path.str;
208
    share->normalized_path.length= path_length;
209
210
    share->version=       refresh_version;
211
212
    share->tablespace=    NULL;
213
214
    /*
215
      This constant is used to mark that no table map version has been
216
      assigned.  No arithmetic is done on the value: it will be
217
      overwritten with a value taken from MYSQL_BIN_LOG.
218
    */
219
    share->table_map_version= ~(uint64_t)0;
220
221
    /*
222
      Since alloc_table_share() can be called without any locking (for
223
      example, ha_create_table... functions), we do not assign a table
224
      map id here.  Instead we assign a value that is not used
225
      elsewhere, and then assign a table map id inside open_table()
226
      under the protection of the LOCK_open mutex.
227
    */
228
    share->table_map_id= ~0UL;
229
    share->cached_row_logging_check= -1;
230
231
    memcpy((char*) &share->mem_root, (char*) &mem_root, sizeof(mem_root));
232
    pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST);
233
    pthread_cond_init(&share->cond, NULL);
234
  }
235
  DBUG_RETURN(share);
236
}
237
238
239
/*
240
  Initialize share for temporary tables
241
242
  SYNOPSIS
243
    init_tmp_table_share()
244
    thd         thread handle
245
    share	Share to fill
246
    key		Table_cache_key, as generated from create_table_def_key.
247
		must start with db name.    
248
    key_length	Length of key
249
    table_name	Table name
250
    path	Path to file (possible in lower case) without .frm
251
252
  NOTES
253
    This is different from alloc_table_share() because temporary tables
254
    don't have to be shared between threads or put into the table def
255
    cache, so we can do some things notable simpler and faster
256
257
    If table is not put in thd->temporary_tables (happens only when
258
    one uses OPEN TEMPORARY) then one can specify 'db' as key and
259
    use key_length= 0 as neither table_cache_key or key_length will be used).
260
*/
261
262
void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key,
263
                          uint key_length, const char *table_name,
264
                          const char *path)
265
{
266
  DBUG_ENTER("init_tmp_table_share");
267
  DBUG_PRINT("enter", ("table: '%s'.'%s'", key, table_name));
268
269
  bzero((char*) share, sizeof(*share));
270
  init_sql_alloc(&share->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
271
  share->table_category=         TABLE_CATEGORY_TEMPORARY;
272
  share->tmp_table=              INTERNAL_TMP_TABLE;
273
  share->db.str=                 (char*) key;
274
  share->db.length=		 strlen(key);
275
  share->table_cache_key.str=    (char*) key;
276
  share->table_cache_key.length= key_length;
277
  share->table_name.str=         (char*) table_name;
278
  share->table_name.length=      strlen(table_name);
279
  share->path.str=               (char*) path;
280
  share->normalized_path.str=    (char*) path;
281
  share->path.length= share->normalized_path.length= strlen(path);
282
  share->frm_version= 		 FRM_VER_TRUE_VARCHAR;
283
  share->tablespace=             NULL;
284
  /*
285
    Temporary tables are not replicated, but we set up these fields
286
    anyway to be able to catch errors.
287
   */
288
  share->table_map_version= ~(uint64_t)0;
289
  share->cached_row_logging_check= -1;
290
291
  /*
292
    table_map_id is also used for MERGE tables to suppress repeated
293
    compatibility checks.
294
  */
295
  share->table_map_id= (ulong) thd->query_id;
296
297
  DBUG_VOID_RETURN;
298
}
299
300
301
/*
302
  Free table share and memory used by it
303
304
  SYNOPSIS
305
    free_table_share()
306
    share		Table share
307
308
  NOTES
309
    share->mutex must be locked when we come here if it's not a temp table
310
*/
311
312
void free_table_share(TABLE_SHARE *share)
313
{
314
  MEM_ROOT mem_root;
315
  DBUG_ENTER("free_table_share");
316
  DBUG_PRINT("enter", ("table: %s.%s", share->db.str, share->table_name.str));
317
  DBUG_ASSERT(share->ref_count == 0);
318
319
  /*
320
    If someone is waiting for this to be deleted, inform it about this.
321
    Don't do a delete until we know that no one is refering to this anymore.
322
  */
323
  if (share->tmp_table == NO_TMP_TABLE)
324
  {
325
    /* share->mutex is locked in release_table_share() */
326
    while (share->waiting_on_cond)
327
    {
328
      pthread_cond_broadcast(&share->cond);
329
      pthread_cond_wait(&share->cond, &share->mutex);
330
    }
331
    /* No thread refers to this anymore */
332
    pthread_mutex_unlock(&share->mutex);
333
    pthread_mutex_destroy(&share->mutex);
334
    pthread_cond_destroy(&share->cond);
335
  }
336
  hash_free(&share->name_hash);
337
  
338
  plugin_unlock(NULL, share->db_plugin);
339
  share->db_plugin= NULL;
340
341
  /* We must copy mem_root from share because share is allocated through it */
342
  memcpy((char*) &mem_root, (char*) &share->mem_root, sizeof(mem_root));
343
  free_root(&mem_root, MYF(0));                 // Free's share
344
  DBUG_VOID_RETURN;
345
}
346
347
348
/**
349
  Return TRUE if a table name matches one of the system table names.
350
  Currently these are:
351
352
  help_category, help_keyword, help_relation, help_topic,
353
  proc, event
354
  time_zone, time_zone_leap_second, time_zone_name, time_zone_transition,
355
  time_zone_transition_type
356
357
  This function trades accuracy for speed, so may return false
358
  positives. Presumably mysql.* database is for internal purposes only
359
  and should not contain user tables.
360
*/
361
362
inline bool is_system_table_name(const char *name, uint length)
363
{
364
  CHARSET_INFO *ci= system_charset_info;
365
366
  return (
367
          /* mysql.proc table */
368
          (
369
           length == 4 &&
370
           my_tolower(ci, name[0]) == 'p' && 
371
           my_tolower(ci, name[1]) == 'r' &&
372
           my_tolower(ci, name[2]) == 'o' &&
373
           my_tolower(ci, name[3]) == 'c'
374
          ) ||
375
376
          /* one of mysql.help* tables */
377
          (
378
           length > 4 &&
379
           my_tolower(ci, name[0]) == 'h' &&
380
           my_tolower(ci, name[1]) == 'e' &&
381
           my_tolower(ci, name[2]) == 'l' &&
382
           my_tolower(ci, name[3]) == 'p'
383
          ) ||
384
385
          /* one of mysql.time_zone* tables */
386
          (
387
           my_tolower(ci, name[0]) == 't' &&
388
           my_tolower(ci, name[1]) == 'i' &&
389
           my_tolower(ci, name[2]) == 'm' &&
390
           my_tolower(ci, name[3]) == 'e'
391
          )
392
          );
393
}
394
395
396
/*
397
  Read table definition from a binary / text based .frm file
398
  
399
  SYNOPSIS
400
  open_table_def()
401
  thd		Thread handler
402
  share		Fill this with table definition
403
  db_flags	Bit mask of the following flags: OPEN_VIEW
404
405
  NOTES
406
    This function is called when the table definition is not cached in
407
    table_def_cache
408
    The data is returned in 'share', which is alloced by
409
    alloc_table_share().. The code assumes that share is initialized.
410
411
  RETURN VALUES
412
   0	ok
413
   1	Error (see open_table_error)
414
   2    Error (see open_table_error)
415
   3    Wrong data in .frm file
416
   4    Error (see open_table_error)
417
   5    Error (see open_table_error: charset unavailable)
418
   6    Unknown .frm version
419
*/
420
421
int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags)
422
{
423
  int error, table_type;
424
  bool error_given;
425
  File file;
426
  uchar head[64], *disk_buff;
427
  char	path[FN_REFLEN];
428
  MEM_ROOT **root_ptr, *old_root;
429
  DBUG_ENTER("open_table_def");
430
  DBUG_PRINT("enter", ("table: '%s'.'%s'  path: '%s'", share->db.str,
431
                       share->table_name.str, share->normalized_path.str));
432
433
  error= 1;
434
  error_given= 0;
435
  disk_buff= NULL;
436
437
  strxmov(path, share->normalized_path.str, reg_ext, NullS);
438
  if ((file= my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0)
439
  {
440
    /*
441
      We don't try to open 5.0 unencoded name, if
442
      - non-encoded name contains '@' signs, 
443
        because '@' can be misinterpreted.
444
        It is not clear if '@' is escape character in 5.1,
445
        or a normal character in 5.0.
446
        
447
      - non-encoded db or table name contain "#mysql50#" prefix.
448
        This kind of tables must have been opened only by the
449
        my_open() above.
450
    */
451
    if (strchr(share->table_name.str, '@') ||
452
        !strncmp(share->db.str, MYSQL50_TABLE_NAME_PREFIX,
453
                 MYSQL50_TABLE_NAME_PREFIX_LENGTH) ||
454
        !strncmp(share->table_name.str, MYSQL50_TABLE_NAME_PREFIX,
455
                 MYSQL50_TABLE_NAME_PREFIX_LENGTH))
456
      goto err_not_open;
457
458
    /* Try unencoded 5.0 name */
459
    uint length;
460
    strxnmov(path, sizeof(path)-1,
461
             mysql_data_home, "/", share->db.str, "/",
462
             share->table_name.str, reg_ext, NullS);
463
    length= unpack_filename(path, path) - reg_ext_length;
464
    /*
465
      The following is a safety test and should never fail
466
      as the old file name should never be longer than the new one.
467
    */
468
    DBUG_ASSERT(length <= share->normalized_path.length);
469
    /*
470
      If the old and the new names have the same length,
471
      then table name does not have tricky characters,
472
      so no need to check the old file name.
473
    */
474
    if (length == share->normalized_path.length ||
475
        ((file= my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0))
476
      goto err_not_open;
477
478
    /* Unencoded 5.0 table name found */
479
    path[length]= '\0'; // Remove .frm extension
480
    strmov(share->normalized_path.str, path);
481
    share->normalized_path.length= length;
482
  }
483
484
  error= 4;
485
  if (my_read(file, head, 64, MYF(MY_NABP)))
486
    goto err;
487
488
  if (head[0] == (uchar) 254 && head[1] == 1)
489
  {
490
    if (head[2] == FRM_VER || head[2] == FRM_VER+1 ||
491
        (head[2] >= FRM_VER+3 && head[2] <= FRM_VER+4))
492
    {
493
      /* Open view only */
494
      if (db_flags & OPEN_VIEW_ONLY)
495
      {
496
        error_given= 1;
497
        goto err;
498
      }
499
      table_type= 1;
500
    }
501
    else
502
    {
503
      error= 6;                                 // Unkown .frm version
504
      goto err;
505
    }
506
  }
507
  else
508
    goto err;
509
510
  /* No handling of text based files yet */
511
  if (table_type == 1)
512
  {
4 by Brian Aker
Remove my_pthread_getspecific_ptr()
513
    root_ptr= (MEM_ROOT **)pthread_getspecific(THR_MALLOC);
1 by brian
clean slate
514
    old_root= *root_ptr;
515
    *root_ptr= &share->mem_root;
516
    error= open_binary_frm(thd, share, head, file);
517
    *root_ptr= old_root;
518
    error_given= 1;
519
  }
520
521
  share->table_category= get_table_category(& share->db, & share->table_name);
522
523
  if (!error)
524
    thd->status_var.opened_shares++;
525
526
err:
527
  my_close(file, MYF(MY_WME));
528
529
err_not_open:
530
  if (error && !error_given)
531
  {
532
    share->error= error;
533
    open_table_error(share, error, (share->open_errno= my_errno), 0);
534
  }
535
536
  DBUG_RETURN(error);
537
}
538
539
540
/*
541
  Read data from a binary .frm file from MySQL 3.23 - 5.0 into TABLE_SHARE
542
*/
543
544
static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
545
                           File file)
546
{
547
  int error, errarg= 0;
548
  uint new_frm_ver, field_pack_length, new_field_pack_flag;
549
  uint interval_count, interval_parts, read_length, int_length;
550
  uint db_create_options, keys, key_parts, n_length;
551
  uint key_info_length, com_length, null_bit_pos;
552
  uint extra_rec_buf_length;
553
  uint i,j;
554
  bool use_hash;
555
  uchar forminfo[288];
556
  char *keynames, *names, *comment_pos;
557
  uchar *record;
558
  uchar *disk_buff, *strpos, *null_flags, *null_pos;
559
  ulong pos, record_offset, *rec_per_key, rec_buff_length;
560
  handler *handler_file= 0;
561
  KEY	*keyinfo;
562
  KEY_PART_INFO *key_part;
563
  SQL_CRYPT *crypted=0;
564
  Field  **field_ptr, *reg_field;
565
  const char **interval_array;
566
  enum legacy_db_type legacy_db_type;
567
  my_bitmap_map *bitmaps;
568
  uchar *buff= 0;
569
  uchar *field_extra_info= 0;
570
  DBUG_ENTER("open_binary_frm");
571
572
  new_field_pack_flag= head[27];
573
  new_frm_ver= (head[2] - FRM_VER);
574
  field_pack_length= new_frm_ver < 2 ? 11 : 17;
575
  disk_buff= 0;
576
577
  error= 3;
578
  if (!(pos=get_form_pos(file,head,(TYPELIB*) 0)))
579
    goto err;                                   /* purecov: inspected */
580
  VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0)));
581
  if (my_read(file,forminfo,288,MYF(MY_NABP)))
582
    goto err;
583
584
  share->frm_version= head[2];
585
  /*
586
    Check if .frm file created by MySQL 5.0. In this case we want to
587
    display CHAR fields as CHAR and not as VARCHAR.
588
    We do it this way as we want to keep the old frm version to enable
589
    MySQL 4.1 to read these files.
590
  */
591
  if (share->frm_version == FRM_VER_TRUE_VARCHAR -1 && head[33] == 5)
592
    share->frm_version= FRM_VER_TRUE_VARCHAR;
593
594
  legacy_db_type= (enum legacy_db_type) (uint) *(head+3);
595
  DBUG_ASSERT(share->db_plugin == NULL);
596
  /*
597
    if the storage engine is dynamic, no point in resolving it by its
598
    dynamically allocated legacy_db_type. We will resolve it later by name.
599
  */
600
  if (legacy_db_type > DB_TYPE_UNKNOWN && 
601
      legacy_db_type < DB_TYPE_FIRST_DYNAMIC)
602
    share->db_plugin= ha_lock_engine(NULL, 
603
                                     ha_checktype(thd, legacy_db_type, 0, 0));
604
  share->db_create_options= db_create_options= uint2korr(head+30);
605
  share->db_options_in_use= share->db_create_options;
606
  share->mysql_version= uint4korr(head+51);
607
  share->null_field_first= 0;
608
  if (!head[32])				// New frm file in 3.23
609
  {
610
    share->avg_row_length= uint4korr(head+34);
611
    share->transactional= (ha_choice) (head[39] & 3);
612
    share->page_checksum= (ha_choice) ((head[39] >> 2) & 3);
613
    share->row_type= (row_type) head[40];
614
    share->table_charset= get_charset((uint) head[38],MYF(0));
615
    share->null_field_first= 1;
616
  }
617
  if (!share->table_charset)
618
  {
619
    /* unknown charset in head[38] or pre-3.23 frm */
620
    if (use_mb(default_charset_info))
621
    {
622
      /* Warn that we may be changing the size of character columns */
623
      sql_print_warning("'%s' had no or invalid character set, "
624
                        "and default character set is multi-byte, "
625
                        "so character column sizes may have changed",
626
                        share->path.str);
627
    }
628
    share->table_charset= default_charset_info;
629
  }
630
  share->db_record_offset= 1;
631
  if (db_create_options & HA_OPTION_LONG_BLOB_PTR)
632
    share->blob_ptr_size= portable_sizeof_char_ptr;
633
  /* Set temporarily a good value for db_low_byte_first */
634
  share->db_low_byte_first= test(legacy_db_type != DB_TYPE_ISAM);
635
  error=4;
636
  share->max_rows= uint4korr(head+18);
637
  share->min_rows= uint4korr(head+22);
638
639
  /* Read keyinformation */
640
  key_info_length= (uint) uint2korr(head+28);
641
  VOID(my_seek(file,(ulong) uint2korr(head+6),MY_SEEK_SET,MYF(0)));
642
  if (read_string(file,(uchar**) &disk_buff,key_info_length))
643
    goto err;                                   /* purecov: inspected */
644
  if (disk_buff[0] & 0x80)
645
  {
646
    share->keys=      keys=      (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
647
    share->key_parts= key_parts= uint2korr(disk_buff+2);
648
  }
649
  else
650
  {
651
    share->keys=      keys=      disk_buff[0];
652
    share->key_parts= key_parts= disk_buff[1];
653
  }
654
  share->keys_for_keyread.init(0);
655
  share->keys_in_use.init(keys);
656
657
  n_length=keys*sizeof(KEY)+key_parts*sizeof(KEY_PART_INFO);
658
  if (!(keyinfo = (KEY*) alloc_root(&share->mem_root,
659
				    n_length + uint2korr(disk_buff+4))))
660
    goto err;                                   /* purecov: inspected */
661
  bzero((char*) keyinfo,n_length);
662
  share->key_info= keyinfo;
663
  key_part= my_reinterpret_cast(KEY_PART_INFO*) (keyinfo+keys);
664
  strpos=disk_buff+6;
665
666
  if (!(rec_per_key= (ulong*) alloc_root(&share->mem_root,
667
					 sizeof(ulong*)*key_parts)))
668
    goto err;
669
670
  for (i=0 ; i < keys ; i++, keyinfo++)
671
  {
672
    keyinfo->table= 0;                           // Updated in open_frm
673
    if (new_frm_ver >= 3)
674
    {
675
      keyinfo->flags=	   (uint) uint2korr(strpos) ^ HA_NOSAME;
676
      keyinfo->key_length= (uint) uint2korr(strpos+2);
677
      keyinfo->key_parts=  (uint) strpos[4];
678
      keyinfo->algorithm=  (enum ha_key_alg) strpos[5];
679
      keyinfo->block_size= uint2korr(strpos+6);
680
      strpos+=8;
681
    }
682
    else
683
    {
684
      keyinfo->flags=	 ((uint) strpos[0]) ^ HA_NOSAME;
685
      keyinfo->key_length= (uint) uint2korr(strpos+1);
686
      keyinfo->key_parts=  (uint) strpos[3];
687
      keyinfo->algorithm= HA_KEY_ALG_UNDEF;
688
      strpos+=4;
689
    }
690
691
    keyinfo->key_part=	 key_part;
692
    keyinfo->rec_per_key= rec_per_key;
693
    for (j=keyinfo->key_parts ; j-- ; key_part++)
694
    {
695
      *rec_per_key++=0;
696
      key_part->fieldnr=	(uint16) (uint2korr(strpos) & FIELD_NR_MASK);
697
      key_part->offset= (uint) uint2korr(strpos+2)-1;
698
      key_part->key_type=	(uint) uint2korr(strpos+5);
699
      // key_part->field=	(Field*) 0;	// Will be fixed later
700
      if (new_frm_ver >= 1)
701
      {
702
	key_part->key_part_flag= *(strpos+4);
703
	key_part->length=	(uint) uint2korr(strpos+7);
704
	strpos+=9;
705
      }
706
      else
707
      {
708
	key_part->length=	*(strpos+4);
709
	key_part->key_part_flag=0;
710
	if (key_part->length > 128)
711
	{
712
	  key_part->length&=127;		/* purecov: inspected */
713
	  key_part->key_part_flag=HA_REVERSE_SORT; /* purecov: inspected */
714
	}
715
	strpos+=7;
716
      }
717
      key_part->store_length=key_part->length;
718
    }
719
  }
720
  keynames=(char*) key_part;
721
  strpos+= (strmov(keynames, (char *) strpos) - keynames)+1;
722
723
  //reading index comments
724
  for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++)
725
  {
726
    if (keyinfo->flags & HA_USES_COMMENT)
727
    {
728
      keyinfo->comment.length= uint2korr(strpos);
729
      keyinfo->comment.str= strmake_root(&share->mem_root, (char*) strpos+2,
730
                                         keyinfo->comment.length);
731
      strpos+= 2 + keyinfo->comment.length;
732
    } 
733
    DBUG_ASSERT(test(keyinfo->flags & HA_USES_COMMENT) == 
734
               (keyinfo->comment.length > 0));
735
  }
736
737
  share->reclength = uint2korr((head+16));
738
  if (*(head+26) == 1)
739
    share->system= 1;				/* one-record-database */
740
741
  record_offset= (ulong) (uint2korr(head+6)+
742
                          ((uint2korr(head+14) == 0xffff ?
743
                            uint4korr(head+47) : uint2korr(head+14))));
744
 
745
  if ((n_length= uint4korr(head+55)))
746
  {
747
    /* Read extra data segment */
748
    uchar *next_chunk, *buff_end;
749
    DBUG_PRINT("info", ("extra segment size is %u bytes", n_length));
750
    if (!(next_chunk= buff= (uchar*) my_malloc(n_length, MYF(MY_WME))))
751
      goto err;
31 by Brian Aker
Removed my versions of pread/pwrite from the Kernel
752
    if (pread(file, buff, n_length, record_offset + share->reclength) == 0)
1 by brian
clean slate
753
    {
754
      goto err;
755
    }
756
    share->connect_string.length= uint2korr(buff);
757
    if (!(share->connect_string.str= strmake_root(&share->mem_root,
758
                                                  (char*) next_chunk + 2,
759
                                                  share->connect_string.
760
                                                  length)))
761
    {
762
      goto err;
763
    }
764
    next_chunk+= share->connect_string.length + 2;
765
    buff_end= buff + n_length;
766
    if (next_chunk + 2 < buff_end)
767
    {
768
      uint str_db_type_length= uint2korr(next_chunk);
769
      LEX_STRING name;
770
      name.str= (char*) next_chunk + 2;
771
      name.length= str_db_type_length;
772
773
      plugin_ref tmp_plugin= ha_resolve_by_name(thd, &name);
774
      if (tmp_plugin != NULL && !plugin_equals(tmp_plugin, share->db_plugin))
775
      {
776
        if (legacy_db_type > DB_TYPE_UNKNOWN &&
777
            legacy_db_type < DB_TYPE_FIRST_DYNAMIC &&
778
            legacy_db_type != ha_legacy_type(
779
                plugin_data(tmp_plugin, handlerton *)))
780
        {
781
          /* bad file, legacy_db_type did not match the name */
782
          my_free(buff, MYF(0));
783
          goto err;
784
        }
785
        /*
786
          tmp_plugin is locked with a local lock.
787
          we unlock the old value of share->db_plugin before
788
          replacing it with a globally locked version of tmp_plugin
789
        */
790
        plugin_unlock(NULL, share->db_plugin);
791
        share->db_plugin= my_plugin_lock(NULL, &tmp_plugin);
792
        DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)",
793
                            str_db_type_length, next_chunk + 2,
794
                            ha_legacy_type(share->db_type())));
795
      }
796
      else if (!tmp_plugin)
797
      {
798
        /* purecov: begin inspected */
799
        error= 8;
800
        my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str);
801
        my_free(buff, MYF(0));
802
        goto err;
803
        /* purecov: end */
804
      }
805
      next_chunk+= str_db_type_length + 2;
806
    }
807
#if MYSQL_VERSION_ID < 50200
808
    if (share->mysql_version >= 50106 && share->mysql_version <= 50109)
809
    {
810
      /*
811
         Partition state array was here in version 5.1.6 to 5.1.9, this code
812
         makes it possible to load a 5.1.6 table in later versions. Can most
813
         likely be removed at some point in time. Will only be used for
814
         upgrades within 5.1 series of versions. Upgrade to 5.2 can only be
815
         done from newer 5.1 versions.
816
      */
817
      next_chunk+= 4;
818
    }
819
    else
820
#endif
821
    if (share->mysql_version >= 50110)
822
    {
823
      /* New auto_partitioned indicator introduced in 5.1.11 */
824
      next_chunk++;
825
    }
826
    if (forminfo[46] == (uchar)255)
827
    {
828
      //reading long table comment
829
      if (next_chunk + 2 > buff_end)
830
      {
831
          DBUG_PRINT("error",
832
                     ("long table comment is not defined in .frm"));
833
          my_free(buff, MYF(0));
834
          goto err;
835
      }
836
      share->comment.length = uint2korr(next_chunk);
837
      if (! (share->comment.str= strmake_root(&share->mem_root,
838
                               (char*)next_chunk + 2, share->comment.length)))
839
      {
840
          my_free(buff, MYF(0));
841
          goto err;
842
      }
843
      next_chunk+= 2 + share->comment.length;
844
    }
845
    DBUG_ASSERT (next_chunk <= buff_end);
846
    if (share->mysql_version >= MYSQL_VERSION_TABLESPACE_IN_FRM_CGE)
847
    {
848
      /*
849
       New frm format in mysql_version 5.2.5 (originally in
850
       mysql-5.1.22-ndb-6.2.5)
851
       New column properties added:
852
       COLUMN_FORMAT DYNAMIC|FIXED and STORAGE DISK|MEMORY
853
       TABLESPACE name is now stored in frm
854
      */
855
      if (next_chunk >= buff_end)
856
      {
857
        if (share->mysql_version >= MYSQL_VERSION_TABLESPACE_IN_FRM)
858
        {
859
          DBUG_PRINT("error", ("Found no field extra info"));
860
          goto err;
861
        }
862
        DBUG_PRINT("info", ("Found no field extra info"));
863
      }
864
      else
865
      {
866
        DBUG_PRINT("info", ("Found field extra info"));
867
        const uint format_section_header_size= 8;
868
        uint format_section_len= uint2korr(next_chunk+0);
869
        uint flags=              uint4korr(next_chunk+2);
870
871
        share->default_storage_media= (enum ha_storage_media) (flags & 0x7);
872
873
        const char *tablespace= (const char*)next_chunk + format_section_header_size;
874
        uint tablespace_len= strlen(tablespace);
875
        if (tablespace_len != 0) 
876
        {
877
          share->tablespace= (char *) alloc_root(&share->mem_root,
878
                                                 tablespace_len+1);
879
          strxmov(share->tablespace, tablespace, NullS);
880
        }
881
        else
882
          share->tablespace= NULL;
883
884
        field_extra_info= next_chunk + format_section_header_size + tablespace_len + 1;
885
        next_chunk+= format_section_len;
886
      }
887
    }
888
    DBUG_ASSERT (next_chunk <= buff_end);
889
    if (next_chunk > buff_end)
890
    {
891
      DBUG_PRINT("error", ("Buffer overflow in field extra info"));
892
      goto err;
893
    }
894
  }
895
  share->key_block_size= uint2korr(head+62);
896
897
  error=4;
898
  extra_rec_buf_length= uint2korr(head+59);
899
  rec_buff_length= ALIGN_SIZE(share->reclength + 1 + extra_rec_buf_length);
900
  share->rec_buff_length= rec_buff_length;
901
  if (!(record= (uchar *) alloc_root(&share->mem_root,
902
                                     rec_buff_length)))
903
    goto err;                                   /* purecov: inspected */
904
  share->default_values= record;
31 by Brian Aker
Removed my versions of pread/pwrite from the Kernel
905
  if (pread(file, record, (size_t) share->reclength, record_offset) == 0)
1 by brian
clean slate
906
    goto err;                                   /* purecov: inspected */
907
908
  VOID(my_seek(file,pos+288,MY_SEEK_SET,MYF(0)));
909
910
  share->fields= uint2korr(forminfo+258);
911
  pos= uint2korr(forminfo+260);			/* Length of all screens */
912
  n_length= uint2korr(forminfo+268);
913
  interval_count= uint2korr(forminfo+270);
914
  interval_parts= uint2korr(forminfo+272);
915
  int_length= uint2korr(forminfo+274);
916
  share->null_fields= uint2korr(forminfo+282);
917
  com_length= uint2korr(forminfo+284);
918
  if (forminfo[46] != (uchar)255)
919
  {
920
    share->comment.length=  (int) (forminfo[46]);
921
    share->comment.str= strmake_root(&share->mem_root, (char*) forminfo+47,
922
                                     share->comment.length);
923
  }
924
925
  DBUG_PRINT("info",("i_count: %d  i_parts: %d  index: %d  n_length: %d  int_length: %d  com_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length));
926
927
  if (!(field_ptr = (Field **)
928
	alloc_root(&share->mem_root,
929
		   (uint) ((share->fields+1)*sizeof(Field*)+
930
			   interval_count*sizeof(TYPELIB)+
931
			   (share->fields+interval_parts+
932
			    keys+3)*sizeof(char *)+
933
			   (n_length+int_length+com_length)))))
934
    goto err;                                   /* purecov: inspected */
935
936
  share->field= field_ptr;
937
  read_length=(uint) (share->fields * field_pack_length +
938
		      pos+ (uint) (n_length+int_length+com_length));
939
  if (read_string(file,(uchar**) &disk_buff,read_length))
940
    goto err;                                   /* purecov: inspected */
941
  strpos= disk_buff+pos;
942
943
  share->intervals= (TYPELIB*) (field_ptr+share->fields+1);
944
  interval_array= (const char **) (share->intervals+interval_count);
945
  names= (char*) (interval_array+share->fields+interval_parts+keys+3);
946
  if (!interval_count)
947
    share->intervals= 0;			// For better debugging
948
  memcpy((char*) names, strpos+(share->fields*field_pack_length),
949
	 (uint) (n_length+int_length));
950
  comment_pos= names+(n_length+int_length);
951
  memcpy(comment_pos, disk_buff+read_length-com_length, com_length);
952
953
  fix_type_pointers(&interval_array, &share->fieldnames, 1, &names);
954
  if (share->fieldnames.count != share->fields)
955
    goto err;
956
  fix_type_pointers(&interval_array, share->intervals, interval_count,
957
		    &names);
958
959
  {
960
    /* Set ENUM and SET lengths */
961
    TYPELIB *interval;
962
    for (interval= share->intervals;
963
         interval < share->intervals + interval_count;
964
         interval++)
965
    {
966
      uint count= (uint) (interval->count + 1) * sizeof(uint);
967
      if (!(interval->type_lengths= (uint *) alloc_root(&share->mem_root,
968
                                                        count)))
969
        goto err;
970
      for (count= 0; count < interval->count; count++)
971
      {
972
        char *val= (char*) interval->type_names[count];
973
        interval->type_lengths[count]= strlen(val);
974
      }
975
      interval->type_lengths[count]= 0;
976
    }
977
  }
978
979
  if (keynames)
980
    fix_type_pointers(&interval_array, &share->keynames, 1, &keynames);
981
982
 /* Allocate handler */
983
  if (!(handler_file= get_new_handler(share, thd->mem_root,
984
                                      share->db_type())))
985
    goto err;
986
987
  record= share->default_values-1;              /* Fieldstart = 1 */
988
  if (share->null_field_first)
989
  {
990
    null_flags= null_pos= (uchar*) record+1;
991
    null_bit_pos= (db_create_options & HA_OPTION_PACK_RECORD) ? 0 : 1;
992
    /*
993
      null_bytes below is only correct under the condition that
994
      there are no bit fields.  Correct values is set below after the
995
      table struct is initialized
996
    */
997
    share->null_bytes= (share->null_fields + null_bit_pos + 7) / 8;
998
  }
999
#ifndef WE_WANT_TO_SUPPORT_VERY_OLD_FRM_FILES
1000
  else
1001
  {
1002
    share->null_bytes= (share->null_fields+7)/8;
1003
    null_flags= null_pos= (uchar*) (record + 1 +share->reclength -
1004
                                    share->null_bytes);
1005
    null_bit_pos= 0;
1006
  }
1007
#endif
1008
1009
  use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
1010
  if (use_hash)
1011
    use_hash= !hash_init(&share->name_hash,
1012
			 system_charset_info,
1013
			 share->fields,0,0,
1014
			 (hash_get_key) get_field_name,0,0);
1015
1016
  for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
1017
  {
1018
    uint pack_flag, interval_nr, unireg_type, recpos, field_length;
1019
    enum_field_types field_type;
1020
    enum ha_storage_media storage_type= HA_SM_DEFAULT;
1021
    enum column_format_type column_format= COLUMN_FORMAT_TYPE_DEFAULT;
1022
    CHARSET_INFO *charset=NULL;
1023
    LEX_STRING comment;
1024
1025
    if (field_extra_info)
1026
    {
1027
      char tmp= field_extra_info[i];
1028
      storage_type= (enum ha_storage_media)(tmp & STORAGE_TYPE_MASK);
1029
      column_format= (enum column_format_type)
1030
                    ((tmp >> COLUMN_FORMAT_SHIFT) & COLUMN_FORMAT_MASK);
1031
      DBUG_PRINT("info", ("Field extra: storage %u format %u",
1032
                          storage_type, column_format));
1033
    }
1034
    if (new_frm_ver >= 3)
1035
    {
1036
      /* new frm file in 4.1 */
1037
      field_length= uint2korr(strpos+3);
1038
      recpos=	    uint3korr(strpos+5);
1039
      pack_flag=    uint2korr(strpos+8);
1040
      unireg_type=  (uint) strpos[10];
1041
      interval_nr=  (uint) strpos[12];
1042
      uint comment_length=uint2korr(strpos+15);
1043
      field_type=(enum_field_types) (uint) strpos[13];
1044
1045
      {
1046
        if (!strpos[14])
1047
          charset= &my_charset_bin;
1048
        else if (!(charset=get_charset((uint) strpos[14], MYF(0))))
1049
        {
1050
          error= 5; // Unknown or unavailable charset
1051
          errarg= (int) strpos[14];
1052
          goto err;
1053
        }
1054
      }
1055
      if (!comment_length)
1056
      {
1057
	comment.str= (char*) "";
1058
	comment.length=0;
1059
      }
1060
      else
1061
      {
1062
	comment.str=    (char*) comment_pos;
1063
	comment.length= comment_length;
1064
	comment_pos+=   comment_length;
1065
      }
1066
    }
1067
    else
1068
    {
1069
      field_length= (uint) strpos[3];
1070
      recpos=	    uint2korr(strpos+4),
1071
      pack_flag=    uint2korr(strpos+6);
1072
      pack_flag&=   ~FIELDFLAG_NO_DEFAULT;     // Safety for old files
1073
      unireg_type=  (uint) strpos[8];
1074
      interval_nr=  (uint) strpos[10];
1075
1076
      /* old frm file */
1077
      field_type= (enum_field_types) f_packtype(pack_flag);
1078
      if (f_is_binary(pack_flag))
1079
      {
1080
        /*
1081
          Try to choose the best 4.1 type:
1082
          - for 4.0 "CHAR(N) BINARY" or "VARCHAR(N) BINARY" 
1083
            try to find a binary collation for character set.
1084
          - for other types (e.g. BLOB) just use my_charset_bin. 
1085
        */
1086
        if (!f_is_blob(pack_flag))
1087
        {
1088
          // 3.23 or 4.0 string
1089
          if (!(charset= get_charset_by_csname(share->table_charset->csname,
1090
                                               MY_CS_BINSORT, MYF(0))))
1091
            charset= &my_charset_bin;
1092
        }
1093
        else
1094
          charset= &my_charset_bin;
1095
      }
1096
      else
1097
        charset= share->table_charset;
1098
      bzero((char*) &comment, sizeof(comment));
1099
    }
1100
1101
    if (interval_nr && charset->mbminlen > 1)
1102
    {
1103
      /* Unescape UCS2 intervals from HEX notation */
1104
      TYPELIB *interval= share->intervals + interval_nr - 1;
1105
      unhex_type2(interval);
1106
    }
1107
    
1108
#ifndef TO_BE_DELETED_ON_PRODUCTION
1109
    if (field_type == MYSQL_TYPE_NEWDECIMAL && !share->mysql_version)
1110
    {
1111
      /*
1112
        Fix pack length of old decimal values from 5.0.3 -> 5.0.4
1113
        The difference is that in the old version we stored precision
1114
        in the .frm table while we now store the display_length
1115
      */
1116
      uint decimals= f_decimals(pack_flag);
1117
      field_length= my_decimal_precision_to_length(field_length,
1118
                                                   decimals,
1119
                                                   f_is_dec(pack_flag) == 0);
1120
      sql_print_error("Found incompatible DECIMAL field '%s' in %s; "
1121
                      "Please do \"ALTER TABLE '%s' FORCE\" to fix it!",
1122
                      share->fieldnames.type_names[i], share->table_name.str,
1123
                      share->table_name.str);
1124
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
1125
                          ER_CRASHED_ON_USAGE,
1126
                          "Found incompatible DECIMAL field '%s' in %s; "
1127
                          "Please do \"ALTER TABLE '%s' FORCE\" to fix it!",
1128
                          share->fieldnames.type_names[i],
1129
                          share->table_name.str,
1130
                          share->table_name.str);
1131
      share->crashed= 1;                        // Marker for CHECK TABLE
1132
    }
1133
#endif
1134
1135
    *field_ptr= reg_field=
1136
      make_field(share, record+recpos,
1137
		 (uint32) field_length,
1138
		 null_pos, null_bit_pos,
1139
		 pack_flag,
1140
		 field_type,
1141
		 charset,
1142
		 (Field::utype) MTYP_TYPENR(unireg_type),
1143
		 (interval_nr ?
1144
		  share->intervals+interval_nr-1 :
1145
		  (TYPELIB*) 0),
1146
		 share->fieldnames.type_names[i]);
1147
    if (!reg_field)				// Not supported field type
1148
    {
1149
      error= 4;
1150
      goto err;			/* purecov: inspected */
1151
    }
1152
1153
    reg_field->flags|= ((uint)storage_type << FIELD_STORAGE_FLAGS);
1154
    reg_field->flags|= ((uint)column_format << COLUMN_FORMAT_FLAGS);
1155
    reg_field->field_index= i;
1156
    reg_field->comment=comment;
1157
    if (!(reg_field->flags & NOT_NULL_FLAG))
1158
    {
1159
      if (!(null_bit_pos= (null_bit_pos + 1) & 7))
1160
        null_pos++;
1161
    }
1162
    if (f_no_default(pack_flag))
1163
      reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
1164
1165
    if (reg_field->unireg_check == Field::NEXT_NUMBER)
1166
      share->found_next_number_field= field_ptr;
1167
    if (share->timestamp_field == reg_field)
1168
      share->timestamp_field_offset= i;
1169
1170
    if (use_hash)
1171
      (void) my_hash_insert(&share->name_hash,
1172
                            (uchar*) field_ptr); // never fail
1173
  }
1174
  *field_ptr=0;					// End marker
1175
1176
  /* Fix key->name and key_part->field */
1177
  if (key_parts)
1178
  {
1179
    uint primary_key=(uint) (find_type((char*) primary_key_name,
1180
				       &share->keynames, 3) - 1);
1181
    longlong ha_option= handler_file->ha_table_flags();
1182
    keyinfo= share->key_info;
1183
    key_part= keyinfo->key_part;
1184
1185
    for (uint key=0 ; key < share->keys ; key++,keyinfo++)
1186
    {
1187
      uint usable_parts= 0;
1188
      keyinfo->name=(char*) share->keynames.type_names[key];
1189
1190
      if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
1191
      {
1192
	/*
1193
	  If the UNIQUE key doesn't have NULL columns and is not a part key
1194
	  declare this as a primary key.
1195
	*/
1196
	primary_key=key;
1197
	for (i=0 ; i < keyinfo->key_parts ;i++)
1198
	{
1199
	  uint fieldnr= key_part[i].fieldnr;
1200
	  if (!fieldnr ||
1201
	      share->field[fieldnr-1]->null_ptr ||
1202
	      share->field[fieldnr-1]->key_length() !=
1203
	      key_part[i].length)
1204
	  {
1205
	    primary_key=MAX_KEY;		// Can't be used
1206
	    break;
1207
	  }
1208
	}
1209
      }
1210
1211
      for (i=0 ; i < keyinfo->key_parts ; key_part++,i++)
1212
      {
1213
        Field *field;
1214
	if (new_field_pack_flag <= 1)
1215
	  key_part->fieldnr= (uint16) find_field(share->field,
1216
                                                 share->default_values,
1217
                                                 (uint) key_part->offset,
1218
                                                 (uint) key_part->length);
1219
	if (!key_part->fieldnr)
1220
        {
1221
          error= 4;                             // Wrong file
1222
          goto err;
1223
        }
1224
        field= key_part->field= share->field[key_part->fieldnr-1];
1225
        key_part->type= field->key_type();
1226
        if (field->null_ptr)
1227
        {
1228
          key_part->null_offset=(uint) ((uchar*) field->null_ptr -
1229
                                        share->default_values);
1230
          key_part->null_bit= field->null_bit;
1231
          key_part->store_length+=HA_KEY_NULL_LENGTH;
1232
          keyinfo->flags|=HA_NULL_PART_KEY;
1233
          keyinfo->extra_length+= HA_KEY_NULL_LENGTH;
1234
          keyinfo->key_length+= HA_KEY_NULL_LENGTH;
1235
        }
1236
        if (field->type() == MYSQL_TYPE_BLOB ||
1237
            field->real_type() == MYSQL_TYPE_VARCHAR)
1238
        {
1239
          if (field->type() == MYSQL_TYPE_BLOB)
1240
            key_part->key_part_flag|= HA_BLOB_PART;
1241
          else
1242
            key_part->key_part_flag|= HA_VAR_LENGTH_PART;
1243
          keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
1244
          key_part->store_length+=HA_KEY_BLOB_LENGTH;
1245
          keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
1246
        }
1247
        if (i == 0 && key != primary_key)
1248
          field->flags |= (((keyinfo->flags & HA_NOSAME) &&
1249
                           (keyinfo->key_parts == 1)) ?
1250
                           UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
1251
        if (i == 0)
1252
          field->key_start.set_bit(key);
1253
        if (field->key_length() == key_part->length &&
1254
            !(field->flags & BLOB_FLAG))
1255
        {
1256
          if (handler_file->index_flags(key, i, 0) & HA_KEYREAD_ONLY)
1257
          {
1258
            share->keys_for_keyread.set_bit(key);
1259
            field->part_of_key.set_bit(key);
1260
            field->part_of_key_not_clustered.set_bit(key);
1261
          }
1262
          if (handler_file->index_flags(key, i, 1) & HA_READ_ORDER)
1263
            field->part_of_sortkey.set_bit(key);
1264
        }
1265
        if (!(key_part->key_part_flag & HA_REVERSE_SORT) &&
1266
            usable_parts == i)
1267
          usable_parts++;			// For FILESORT
1268
        field->flags|= PART_KEY_FLAG;
1269
        if (key == primary_key)
1270
        {
1271
          field->flags|= PRI_KEY_FLAG;
1272
          /*
1273
            If this field is part of the primary key and all keys contains
1274
            the primary key, then we can use any key to find this column
1275
          */
1276
          if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX)
1277
          {
1278
            field->part_of_key= share->keys_in_use;
1279
            if (field->part_of_sortkey.is_set(key))
1280
              field->part_of_sortkey= share->keys_in_use;
1281
          }
1282
        }
1283
        if (field->key_length() != key_part->length)
1284
        {
1285
#ifndef TO_BE_DELETED_ON_PRODUCTION
1286
          if (field->type() == MYSQL_TYPE_NEWDECIMAL)
1287
          {
1288
            /*
1289
              Fix a fatal error in decimal key handling that causes crashes
1290
              on Innodb. We fix it by reducing the key length so that
1291
              InnoDB never gets a too big key when searching.
1292
              This allows the end user to do an ALTER TABLE to fix the
1293
              error.
1294
            */
1295
            keyinfo->key_length-= (key_part->length - field->key_length());
1296
            key_part->store_length-= (uint16)(key_part->length -
1297
                                              field->key_length());
1298
            key_part->length= (uint16)field->key_length();
1299
            sql_print_error("Found wrong key definition in %s; "
1300
                            "Please do \"ALTER TABLE '%s' FORCE \" to fix it!",
1301
                            share->table_name.str,
1302
                            share->table_name.str);
1303
            push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
1304
                                ER_CRASHED_ON_USAGE,
1305
                                "Found wrong key definition in %s; "
1306
                                "Please do \"ALTER TABLE '%s' FORCE\" to fix "
1307
                                "it!",
1308
                                share->table_name.str,
1309
                                share->table_name.str);
1310
            share->crashed= 1;                // Marker for CHECK TABLE
1311
            continue;
1312
          }
1313
#endif
1314
          key_part->key_part_flag|= HA_PART_KEY_SEG;
1315
        }
1316
      }
1317
      keyinfo->usable_key_parts= usable_parts; // Filesort
1318
1319
      set_if_bigger(share->max_key_length,keyinfo->key_length+
1320
                    keyinfo->key_parts);
1321
      share->total_key_length+= keyinfo->key_length;
1322
      /*
1323
        MERGE tables do not have unique indexes. But every key could be
1324
        an unique index on the underlying MyISAM table. (Bug #10400)
1325
      */
1326
      if ((keyinfo->flags & HA_NOSAME) ||
1327
          (ha_option & HA_ANY_INDEX_MAY_BE_UNIQUE))
1328
        set_if_bigger(share->max_unique_length,keyinfo->key_length);
1329
    }
1330
    if (primary_key < MAX_KEY &&
1331
	(share->keys_in_use.is_set(primary_key)))
1332
    {
1333
      share->primary_key= primary_key;
1334
      /*
1335
	If we are using an integer as the primary key then allow the user to
1336
	refer to it as '_rowid'
1337
      */
1338
      if (share->key_info[primary_key].key_parts == 1)
1339
      {
1340
	Field *field= share->key_info[primary_key].key_part[0].field;
1341
	if (field && field->result_type() == INT_RESULT)
1342
        {
1343
          /* note that fieldnr here (and rowid_field_offset) starts from 1 */
1344
	  share->rowid_field_offset= (share->key_info[primary_key].key_part[0].
1345
                                      fieldnr);
1346
        }
1347
      }
1348
    }
1349
    else
1350
      share->primary_key = MAX_KEY; // we do not have a primary key
1351
  }
1352
  else
1353
    share->primary_key= MAX_KEY;
1354
  x_free((uchar*) disk_buff);
1355
  disk_buff=0;
1356
  if (new_field_pack_flag <= 1)
1357
  {
1358
    /* Old file format with default as not null */
1359
    uint null_length= (share->null_fields+7)/8;
1360
    bfill(share->default_values + (null_flags - (uchar*) record),
1361
          null_length, 255);
1362
  }
1363
1364
  if (share->found_next_number_field)
1365
  {
1366
    reg_field= *share->found_next_number_field;
1367
    if ((int) (share->next_number_index= (uint)
1368
	       find_ref_key(share->key_info, share->keys,
1369
                            share->default_values, reg_field,
1370
			    &share->next_number_key_offset,
1371
                            &share->next_number_keypart)) < 0)
1372
    {
1373
      /* Wrong field definition */
1374
      error= 4;
1375
      goto err;
1376
    }
1377
    else
1378
      reg_field->flags |= AUTO_INCREMENT_FLAG;
1379
  }
1380
1381
  if (share->blob_fields)
1382
  {
1383
    Field **ptr;
1384
    uint k, *save;
1385
1386
    /* Store offsets to blob fields to find them fast */
1387
    if (!(share->blob_field= save=
1388
	  (uint*) alloc_root(&share->mem_root,
1389
                             (uint) (share->blob_fields* sizeof(uint)))))
1390
      goto err;
1391
    for (k=0, ptr= share->field ; *ptr ; ptr++, k++)
1392
    {
1393
      if ((*ptr)->flags & BLOB_FLAG)
1394
	(*save++)= k;
1395
    }
1396
  }
1397
1398
  /*
1399
    the correct null_bytes can now be set, since bitfields have been taken
1400
    into account
1401
  */
1402
  share->null_bytes= (null_pos - (uchar*) null_flags +
1403
                      (null_bit_pos + 7) / 8);
1404
  share->last_null_bit_pos= null_bit_pos;
1405
1406
  share->db_low_byte_first= handler_file->low_byte_first();
1407
  share->column_bitmap_size= bitmap_buffer_size(share->fields);
1408
1409
  if (!(bitmaps= (my_bitmap_map*) alloc_root(&share->mem_root,
1410
                                             share->column_bitmap_size)))
1411
    goto err;
1412
  bitmap_init(&share->all_set, bitmaps, share->fields, FALSE);
1413
  bitmap_set_all(&share->all_set);
1414
1415
  delete handler_file;
1416
#ifndef DBUG_OFF
1417
  if (use_hash)
1418
    (void) hash_check(&share->name_hash);
1419
#endif
1420
  if (buff)
1421
    my_free(buff, MYF(0));
1422
  DBUG_RETURN (0);
1423
1424
 err:
1425
  if (buff)
1426
    my_free(buff, MYF(0));
1427
  share->error= error;
1428
  share->open_errno= my_errno;
1429
  share->errarg= errarg;
1430
  x_free((uchar*) disk_buff);
1431
  delete crypted;
1432
  delete handler_file;
1433
  hash_free(&share->name_hash);
1434
1435
  open_table_error(share, error, share->open_errno, errarg);
1436
  DBUG_RETURN(error);
1437
} /* open_binary_frm */
1438
1439
1440
/*
1441
  Open a table based on a TABLE_SHARE
1442
1443
  SYNOPSIS
1444
    open_table_from_share()
1445
    thd			Thread handler
1446
    share		Table definition
1447
    alias       	Alias for table
1448
    db_stat		open flags (for example HA_OPEN_KEYFILE|
1449
    			HA_OPEN_RNDFILE..) can be 0 (example in
1450
                        ha_example_table)
1451
    prgflag   		READ_ALL etc..
1452
    ha_open_flags	HA_OPEN_ABORT_IF_LOCKED etc..
1453
    outparam       	result table
1454
    open_mode           One of OTM_OPEN|OTM_CREATE|OTM_ALTER
1455
                        if OTM_CREATE some errors are ignore
1456
                        if OTM_ALTER HA_OPEN is not called
1457
1458
  RETURN VALUES
1459
   0	ok
1460
   1	Error (see open_table_error)
1461
   2    Error (see open_table_error)
1462
   3    Wrong data in .frm file
1463
   4    Error (see open_table_error)
1464
   5    Error (see open_table_error: charset unavailable)
1465
   7    Table definition has changed in engine
1466
*/
1467
1468
int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
1469
                          uint db_stat, uint prgflag, uint ha_open_flags,
1470
                          TABLE *outparam, open_table_mode open_mode)
1471
{
1472
  int error;
1473
  uint records, i, bitmap_size;
1474
  bool error_reported= FALSE;
1475
  uchar *record, *bitmaps;
1476
  Field **field_ptr;
1477
  DBUG_ENTER("open_table_from_share");
1478
  DBUG_PRINT("enter",("name: '%s.%s'  form: 0x%lx, open mode:%s",
1479
                      share->db.str,
1480
                      share->table_name.str,
1481
                      (long) outparam,
1482
                      (open_mode == OTM_OPEN)?"open":
1483
                      ((open_mode == OTM_CREATE)?"create":"alter")));
1484
1485
  /* Parsing of partitioning information from .frm needs thd->lex set up. */
1486
  DBUG_ASSERT(thd->lex->is_lex_started);
1487
1488
  error= 1;
1489
  bzero((char*) outparam, sizeof(*outparam));
1490
  outparam->in_use= thd;
1491
  outparam->s= share;
1492
  outparam->db_stat= db_stat;
1493
  outparam->write_row_record= NULL;
1494
1495
  init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
1496
1497
  if (!(outparam->alias= my_strdup(alias, MYF(MY_WME))))
1498
    goto err;
1499
  outparam->quick_keys.init();
1500
  outparam->covering_keys.init();
1501
  outparam->keys_in_use_for_query.init();
1502
1503
  /* Allocate handler */
1504
  outparam->file= 0;
1505
  if (!(prgflag & OPEN_FRM_FILE_ONLY))
1506
  {
1507
    if (!(outparam->file= get_new_handler(share, &outparam->mem_root,
1508
                                          share->db_type())))
1509
      goto err;
1510
  }
1511
  else
1512
  {
1513
    DBUG_ASSERT(!db_stat);
1514
  }
1515
1516
  error= 4;
1517
  outparam->reginfo.lock_type= TL_UNLOCK;
1518
  outparam->current_lock= F_UNLCK;
1519
  records=0;
1520
  if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN))
1521
    records=1;
1522
  if (prgflag & (READ_ALL+EXTRA_RECORD))
1523
    records++;
1524
1525
  if (!(record= (uchar*) alloc_root(&outparam->mem_root,
1526
                                   share->rec_buff_length * records)))
1527
    goto err;                                   /* purecov: inspected */
1528
1529
  if (records == 0)
1530
  {
1531
    /* We are probably in hard repair, and the buffers should not be used */
1532
    outparam->record[0]= outparam->record[1]= share->default_values;
1533
  }
1534
  else
1535
  {
1536
    outparam->record[0]= record;
1537
    if (records > 1)
1538
      outparam->record[1]= record+ share->rec_buff_length;
1539
    else
1540
      outparam->record[1]= outparam->record[0];   // Safety
1541
  }
1542
1543
#ifdef HAVE_purify
1544
  /*
1545
    We need this because when we read var-length rows, we are not updating
1546
    bytes after end of varchar
1547
  */
1548
  if (records > 1)
1549
  {
1550
    memcpy(outparam->record[0], share->default_values, share->rec_buff_length);
1551
    memcpy(outparam->record[1], share->default_values, share->null_bytes);
1552
    if (records > 2)
1553
      memcpy(outparam->record[1], share->default_values,
1554
             share->rec_buff_length);
1555
  }
1556
#endif
1557
1558
  if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root,
1559
                                          (uint) ((share->fields+1)*
1560
                                                  sizeof(Field*)))))
1561
    goto err;                                   /* purecov: inspected */
1562
1563
  outparam->field= field_ptr;
1564
1565
  record= (uchar*) outparam->record[0]-1;	/* Fieldstart = 1 */
1566
  if (share->null_field_first)
1567
    outparam->null_flags= (uchar*) record+1;
1568
  else
1569
    outparam->null_flags= (uchar*) (record+ 1+ share->reclength -
1570
                                    share->null_bytes);
1571
1572
  /* Setup copy of fields from share, but use the right alias and record */
1573
  for (i=0 ; i < share->fields; i++, field_ptr++)
1574
  {
1575
    if (!((*field_ptr)= share->field[i]->clone(&outparam->mem_root, outparam)))
1576
      goto err;
1577
  }
1578
  (*field_ptr)= 0;                              // End marker
1579
1580
  if (share->found_next_number_field)
1581
    outparam->found_next_number_field=
1582
      outparam->field[(uint) (share->found_next_number_field - share->field)];
1583
  if (share->timestamp_field)
1584
    outparam->timestamp_field= (Field_timestamp*) outparam->field[share->timestamp_field_offset];
1585
1586
1587
  /* Fix key->name and key_part->field */
1588
  if (share->key_parts)
1589
  {
1590
    KEY	*key_info, *key_info_end;
1591
    KEY_PART_INFO *key_part;
1592
    uint n_length;
1593
    n_length= share->keys*sizeof(KEY) + share->key_parts*sizeof(KEY_PART_INFO);
1594
    if (!(key_info= (KEY*) alloc_root(&outparam->mem_root, n_length)))
1595
      goto err;
1596
    outparam->key_info= key_info;
1597
    key_part= (my_reinterpret_cast(KEY_PART_INFO*) (key_info+share->keys));
1598
    
1599
    memcpy(key_info, share->key_info, sizeof(*key_info)*share->keys);
1600
    memcpy(key_part, share->key_info[0].key_part, (sizeof(*key_part) *
1601
                                                   share->key_parts));
1602
1603
    for (key_info_end= key_info + share->keys ;
1604
         key_info < key_info_end ;
1605
         key_info++)
1606
    {
1607
      KEY_PART_INFO *key_part_end;
1608
1609
      key_info->table= outparam;
1610
      key_info->key_part= key_part;
1611
1612
      for (key_part_end= key_part+ key_info->key_parts ;
1613
           key_part < key_part_end ;
1614
           key_part++)
1615
      {
1616
        Field *field= key_part->field= outparam->field[key_part->fieldnr-1];
1617
1618
        if (field->key_length() != key_part->length &&
1619
            !(field->flags & BLOB_FLAG))
1620
        {
1621
          /*
1622
            We are using only a prefix of the column as a key:
1623
            Create a new field for the key part that matches the index
1624
          */
1625
          field= key_part->field=field->new_field(&outparam->mem_root,
1626
                                                  outparam, 0);
1627
          field->field_length= key_part->length;
1628
        }
1629
      }
1630
    }
1631
  }
1632
1633
  /* Allocate bitmaps */
1634
1635
  bitmap_size= share->column_bitmap_size;
1636
  if (!(bitmaps= (uchar*) alloc_root(&outparam->mem_root, bitmap_size*3)))
1637
    goto err;
1638
  bitmap_init(&outparam->def_read_set,
1639
              (my_bitmap_map*) bitmaps, share->fields, FALSE);
1640
  bitmap_init(&outparam->def_write_set,
1641
              (my_bitmap_map*) (bitmaps+bitmap_size), share->fields, FALSE);
1642
  bitmap_init(&outparam->tmp_set,
1643
              (my_bitmap_map*) (bitmaps+bitmap_size*2), share->fields, FALSE);
1644
  outparam->default_column_bitmaps();
1645
1646
  /* The table struct is now initialized;  Open the table */
1647
  error= 2;
1648
  if (db_stat && open_mode != OTM_ALTER)
1649
  {
1650
    int ha_err;
1651
    if ((ha_err= (outparam->file->
1652
                  ha_open(outparam, share->normalized_path.str,
1653
                          (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
1654
                          (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
1655
                           ((db_stat & HA_WAIT_IF_LOCKED) ||
1656
                            (specialflag & SPECIAL_WAIT_IF_LOCKED)) ?
1657
                           HA_OPEN_WAIT_IF_LOCKED :
1658
                           (db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
1659
                          HA_OPEN_ABORT_IF_LOCKED :
1660
                           HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
1661
    {
1662
      /* Set a flag if the table is crashed and it can be auto. repaired */
1663
      share->crashed= ((ha_err == HA_ERR_CRASHED_ON_USAGE) &&
1664
                       outparam->file->auto_repair() &&
1665
                       !(ha_open_flags & HA_OPEN_FOR_REPAIR));
1666
1667
      switch (ha_err)
1668
      {
1669
        case HA_ERR_NO_SUCH_TABLE:
1670
	  /*
1671
            The table did not exists in storage engine, use same error message
1672
            as if the .frm file didn't exist
1673
          */
1674
	  error= 1;
1675
	  my_errno= ENOENT;
1676
          break;
1677
        case EMFILE:
1678
	  /*
1679
            Too many files opened, use same error message as if the .frm
1680
            file can't open
1681
           */
1682
          DBUG_PRINT("error", ("open file: %s failed, too many files opened (errno: %d)", 
1683
		  share->normalized_path.str, ha_err));
1684
	  error= 1;
1685
	  my_errno= EMFILE;
1686
          break;
1687
        default:
1688
          outparam->file->print_error(ha_err, MYF(0));
1689
          error_reported= TRUE;
1690
          if (ha_err == HA_ERR_TABLE_DEF_CHANGED)
1691
            error= 7;
1692
          break;
1693
      }
1694
      goto err;                                 /* purecov: inspected */
1695
    }
1696
  }
1697
1698
#if defined(HAVE_purify) && !defined(DBUG_OFF)
1699
  bzero((char*) bitmaps, bitmap_size*3);
1700
#endif
1701
1702
  outparam->no_replicate= outparam->file &&
1703
                          test(outparam->file->ha_table_flags() &
1704
                               HA_HAS_OWN_BINLOGGING);
1705
  thd->status_var.opened_tables++;
1706
1707
  DBUG_RETURN (0);
1708
1709
 err:
1710
  if (!error_reported && !(prgflag & DONT_GIVE_ERROR))
1711
    open_table_error(share, error, my_errno, 0);
1712
  delete outparam->file;
1713
  outparam->file= 0;				// For easier error checking
1714
  outparam->db_stat=0;
1715
  free_root(&outparam->mem_root, MYF(0));       // Safe to call on bzero'd root
1716
  my_free((char*) outparam->alias, MYF(MY_ALLOW_ZERO_PTR));
1717
  DBUG_RETURN (error);
1718
}
1719
1720
1721
/*
1722
  Free information allocated by openfrm
1723
1724
  SYNOPSIS
1725
    closefrm()
1726
    table		TABLE object to free
1727
    free_share		Is 1 if we also want to free table_share
1728
*/
1729
1730
int closefrm(register TABLE *table, bool free_share)
1731
{
1732
  int error=0;
1733
  DBUG_ENTER("closefrm");
1734
  DBUG_PRINT("enter", ("table: 0x%lx", (long) table));
1735
1736
  if (table->db_stat)
1737
    error=table->file->close();
1738
  my_free((char*) table->alias, MYF(MY_ALLOW_ZERO_PTR));
1739
  table->alias= 0;
1740
  if (table->field)
1741
  {
1742
    for (Field **ptr=table->field ; *ptr ; ptr++)
1743
      delete *ptr;
1744
    table->field= 0;
1745
  }
1746
  delete table->file;
1747
  table->file= 0;				/* For easier errorchecking */
1748
  if (free_share)
1749
  {
1750
    if (table->s->tmp_table == NO_TMP_TABLE)
1751
      release_table_share(table->s, RELEASE_NORMAL);
1752
    else
1753
      free_table_share(table->s);
1754
  }
1755
  free_root(&table->mem_root, MYF(0));
1756
  DBUG_RETURN(error);
1757
}
1758
1759
1760
/* Deallocate temporary blob storage */
1761
1762
void free_blobs(register TABLE *table)
1763
{
1764
  uint *ptr, *end;
1765
  for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ;
1766
       ptr != end ;
1767
       ptr++)
1768
    ((Field_blob*) table->field[*ptr])->free();
1769
}
1770
1771
1772
	/* Find where a form starts */
1773
	/* if formname is NullS then only formnames is read */
1774
1775
ulong get_form_pos(File file, uchar *head, TYPELIB *save_names)
1776
{
1777
  uint a_length,names,length;
1778
  uchar *pos,*buf;
1779
  ulong ret_value=0;
1780
  DBUG_ENTER("get_form_pos");
1781
1782
  names=uint2korr(head+8);
1783
  a_length=(names+2)*sizeof(char *);		/* Room for two extra */
1784
1785
  if (!save_names)
1786
    a_length=0;
1787
  else
1788
    save_names->type_names=0;			/* Clear if error */
1789
1790
  if (names)
1791
  {
1792
    length=uint2korr(head+4);
1793
    VOID(my_seek(file,64L,MY_SEEK_SET,MYF(0)));
1794
    if (!(buf= (uchar*) my_malloc((size_t) length+a_length+names*4,
1795
				  MYF(MY_WME))) ||
1796
	my_read(file, buf+a_length, (size_t) (length+names*4),
1797
		MYF(MY_NABP)))
1798
    {						/* purecov: inspected */
1799
      x_free((uchar*) buf);			/* purecov: inspected */
1800
      DBUG_RETURN(0L);				/* purecov: inspected */
1801
    }
1802
    pos= buf+a_length+length;
1803
    ret_value=uint4korr(pos);
1804
  }
1805
  if (! save_names)
1806
  {
1807
    if (names)
1808
      my_free((uchar*) buf,MYF(0));
1809
  }
1810
  else if (!names)
1811
    bzero((char*) save_names,sizeof(save_names));
1812
  else
1813
  {
1814
    char *str;
1815
    str=(char *) (buf+a_length);
1816
    fix_type_pointers((const char ***) &buf,save_names,1,&str);
1817
  }
1818
  DBUG_RETURN(ret_value);
1819
}
1820
1821
1822
/*
1823
  Read string from a file with malloc
1824
1825
  NOTES:
1826
    We add an \0 at end of the read string to make reading of C strings easier
1827
*/
1828
1829
int read_string(File file, uchar**to, size_t length)
1830
{
1831
  DBUG_ENTER("read_string");
1832
1833
  x_free(*to);
1834
  if (!(*to= (uchar*) my_malloc(length+1,MYF(MY_WME))) ||
1835
      my_read(file, *to, length,MYF(MY_NABP)))
1836
  {
1837
    x_free(*to);                              /* purecov: inspected */
1838
    *to= 0;                                   /* purecov: inspected */
1839
    DBUG_RETURN(1);                           /* purecov: inspected */
1840
  }
1841
  *((char*) *to+length)= '\0';
1842
  DBUG_RETURN (0);
1843
} /* read_string */
1844
1845
1846
	/* Add a new form to a form file */
1847
1848
ulong make_new_entry(File file, uchar *fileinfo, TYPELIB *formnames,
1849
		     const char *newname)
1850
{
1851
  uint i,bufflength,maxlength,n_length,length,names;
1852
  ulong endpos,newpos;
1853
  uchar buff[IO_SIZE];
1854
  uchar *pos;
1855
  DBUG_ENTER("make_new_entry");
1856
1857
  length=(uint) strlen(newname)+1;
1858
  n_length=uint2korr(fileinfo+4);
1859
  maxlength=uint2korr(fileinfo+6);
1860
  names=uint2korr(fileinfo+8);
1861
  newpos=uint4korr(fileinfo+10);
1862
1863
  if (64+length+n_length+(names+1)*4 > maxlength)
1864
  {						/* Expand file */
1865
    newpos+=IO_SIZE;
1866
    int4store(fileinfo+10,newpos);
1867
    endpos=(ulong) my_seek(file,0L,MY_SEEK_END,MYF(0));/* Copy from file-end */
1868
    bufflength= (uint) (endpos & (IO_SIZE-1));	/* IO_SIZE is a power of 2 */
1869
1870
    while (endpos > maxlength)
1871
    {
1872
      VOID(my_seek(file,(ulong) (endpos-bufflength),MY_SEEK_SET,MYF(0)));
1873
      if (my_read(file, buff, bufflength, MYF(MY_NABP+MY_WME)))
1874
	DBUG_RETURN(0L);
1875
      VOID(my_seek(file,(ulong) (endpos-bufflength+IO_SIZE),MY_SEEK_SET,
1876
		   MYF(0)));
1877
      if ((my_write(file, buff,bufflength,MYF(MY_NABP+MY_WME))))
1878
	DBUG_RETURN(0);
1879
      endpos-=bufflength; bufflength=IO_SIZE;
1880
    }
1881
    bzero(buff,IO_SIZE);			/* Null new block */
1882
    VOID(my_seek(file,(ulong) maxlength,MY_SEEK_SET,MYF(0)));
1883
    if (my_write(file,buff,bufflength,MYF(MY_NABP+MY_WME)))
1884
	DBUG_RETURN(0L);
1885
    maxlength+=IO_SIZE;				/* Fix old ref */
1886
    int2store(fileinfo+6,maxlength);
1887
    for (i=names, pos= (uchar*) *formnames->type_names+n_length-1; i-- ;
1888
	 pos+=4)
1889
    {
1890
      endpos=uint4korr(pos)+IO_SIZE;
1891
      int4store(pos,endpos);
1892
    }
1893
  }
1894
1895
  if (n_length == 1 )
1896
  {						/* First name */
1897
    length++;
1898
    VOID(strxmov((char*) buff,"/",newname,"/",NullS));
1899
  }
1900
  else
1901
    VOID(strxmov((char*) buff,newname,"/",NullS)); /* purecov: inspected */
1902
  VOID(my_seek(file,63L+(ulong) n_length,MY_SEEK_SET,MYF(0)));
1903
  if (my_write(file, buff, (size_t) length+1,MYF(MY_NABP+MY_WME)) ||
1904
      (names && my_write(file,(uchar*) (*formnames->type_names+n_length-1),
1905
			 names*4, MYF(MY_NABP+MY_WME))) ||
1906
      my_write(file, fileinfo+10, 4,MYF(MY_NABP+MY_WME)))
1907
    DBUG_RETURN(0L); /* purecov: inspected */
1908
1909
  int2store(fileinfo+8,names+1);
1910
  int2store(fileinfo+4,n_length+length);
30 by Brian Aker
Large file and ftruncate() support
1911
  (void)ftruncate(file, newpos);/* Append file with '\0' */
1 by brian
clean slate
1912
  DBUG_RETURN(newpos);
1913
} /* make_new_entry */
1914
1915
1916
	/* error message when opening a form file */
1917
1918
void open_table_error(TABLE_SHARE *share, int error, int db_errno, int errarg)
1919
{
1920
  int err_no;
1921
  char buff[FN_REFLEN];
1922
  myf errortype= ME_ERROR+ME_WAITTANG;
1923
  DBUG_ENTER("open_table_error");
1924
1925
  switch (error) {
1926
  case 7:
1927
  case 1:
1928
    if (db_errno == ENOENT)
1929
      my_error(ER_NO_SUCH_TABLE, MYF(0), share->db.str, share->table_name.str);
1930
    else
1931
    {
1932
      strxmov(buff, share->normalized_path.str, reg_ext, NullS);
1933
      my_error((db_errno == EMFILE) ? ER_CANT_OPEN_FILE : ER_FILE_NOT_FOUND,
1934
               errortype, buff, db_errno);
1935
    }
1936
    break;
1937
  case 2:
1938
  {
1939
    handler *file= 0;
1940
    const char *datext= "";
1941
    
1942
    if (share->db_type() != NULL)
1943
    {
1944
      if ((file= get_new_handler(share, current_thd->mem_root,
1945
                                 share->db_type())))
1946
      {
1947
        if (!(datext= *file->bas_ext()))
1948
          datext= "";
1949
      }
1950
    }
1951
    err_no= (db_errno == ENOENT) ? ER_FILE_NOT_FOUND : (db_errno == EAGAIN) ?
1952
      ER_FILE_USED : ER_CANT_OPEN_FILE;
1953
    strxmov(buff, share->normalized_path.str, datext, NullS);
1954
    my_error(err_no,errortype, buff, db_errno);
1955
    delete file;
1956
    break;
1957
  }
1958
  case 5:
1959
  {
1960
    const char *csname= get_charset_name((uint) errarg);
1961
    char tmp[10];
1962
    if (!csname || csname[0] =='?')
1963
    {
1964
      my_snprintf(tmp, sizeof(tmp), "#%d", errarg);
1965
      csname= tmp;
1966
    }
1967
    my_printf_error(ER_UNKNOWN_COLLATION,
1968
                    "Unknown collation '%s' in table '%-.64s' definition", 
1969
                    MYF(0), csname, share->table_name.str);
1970
    break;
1971
  }
1972
  case 6:
1973
    strxmov(buff, share->normalized_path.str, reg_ext, NullS);
1974
    my_printf_error(ER_NOT_FORM_FILE,
1975
                    "Table '%-.64s' was created with a different version "
1976
                    "of MySQL and cannot be read", 
1977
                    MYF(0), buff);
1978
    break;
1979
  case 8:
1980
    break;
1981
  default:				/* Better wrong error than none */
1982
  case 4:
1983
    strxmov(buff, share->normalized_path.str, reg_ext, NullS);
1984
    my_error(ER_NOT_FORM_FILE, errortype, buff, 0);
1985
    break;
1986
  }
1987
  DBUG_VOID_RETURN;
1988
} /* open_table_error */
1989
1990
1991
	/*
1992
	** fix a str_type to a array type
1993
	** typeparts separated with some char. differents types are separated
1994
	** with a '\0'
1995
	*/
1996
1997
static void
1998
fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types,
1999
		  char **names)
2000
{
2001
  char *type_name, *ptr;
2002
  char chr;
2003
2004
  ptr= *names;
2005
  while (types--)
2006
  {
2007
    point_to_type->name=0;
2008
    point_to_type->type_names= *array;
2009
2010
    if ((chr= *ptr))			/* Test if empty type */
2011
    {
2012
      while ((type_name=strchr(ptr+1,chr)) != NullS)
2013
      {
2014
	*((*array)++) = ptr+1;
2015
	*type_name= '\0';		/* End string */
2016
	ptr=type_name;
2017
      }
2018
      ptr+=2;				/* Skip end mark and last 0 */
2019
    }
2020
    else
2021
      ptr++;
2022
    point_to_type->count= (uint) (*array - point_to_type->type_names);
2023
    point_to_type++;
2024
    *((*array)++)= NullS;		/* End of type */
2025
  }
2026
  *names=ptr;				/* Update end */
2027
  return;
2028
} /* fix_type_pointers */
2029
2030
2031
TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings)
2032
{
2033
  TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
2034
  if (!result)
2035
    return 0;
2036
  result->count=strings.elements;
2037
  result->name="";
2038
  uint nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1);
2039
  if (!(result->type_names= (const char**) alloc_root(mem_root, nbytes)))
2040
    return 0;
2041
  result->type_lengths= (uint*) (result->type_names + result->count + 1);
2042
  List_iterator<String> it(strings);
2043
  String *tmp;
2044
  for (uint i=0; (tmp=it++) ; i++)
2045
  {
2046
    result->type_names[i]= tmp->ptr();
2047
    result->type_lengths[i]= tmp->length();
2048
  }
2049
  result->type_names[result->count]= 0;		// End marker
2050
  result->type_lengths[result->count]= 0;
2051
  return result;
2052
}
2053
2054
2055
/*
2056
 Search after a field with given start & length
2057
 If an exact field isn't found, return longest field with starts
2058
 at right position.
2059
 
2060
 NOTES
2061
   This is needed because in some .frm fields 'fieldnr' was saved wrong
2062
2063
 RETURN
2064
   0  error
2065
   #  field number +1
2066
*/
2067
2068
static uint find_field(Field **fields, uchar *record, uint start, uint length)
2069
{
2070
  Field **field;
2071
  uint i, pos;
2072
2073
  pos= 0;
2074
  for (field= fields, i=1 ; *field ; i++,field++)
2075
  {
2076
    if ((*field)->offset(record) == start)
2077
    {
2078
      if ((*field)->key_length() == length)
2079
	return (i);
2080
      if (!pos || fields[pos-1]->pack_length() <
2081
	  (*field)->pack_length())
2082
	pos= i;
2083
    }
2084
  }
2085
  return (pos);
2086
}
2087
2088
2089
	/* Check that the integer is in the internal */
2090
2091
int set_zone(register int nr, int min_zone, int max_zone)
2092
{
2093
  if (nr<=min_zone)
2094
    return (min_zone);
2095
  if (nr>=max_zone)
2096
    return (max_zone);
2097
  return (nr);
2098
} /* set_zone */
2099
2100
	/* Adjust number to next larger disk buffer */
2101
2102
ulong next_io_size(register ulong pos)
2103
{
2104
  register ulong offset;
2105
  if ((offset= pos & (IO_SIZE-1)))
2106
    return pos-offset+IO_SIZE;
2107
  return pos;
2108
} /* next_io_size */
2109
2110
2111
/*
2112
  Store an SQL quoted string.
2113
2114
  SYNOPSIS  
2115
    append_unescaped()
2116
    res		result String
2117
    pos		string to be quoted
2118
    length	it's length
2119
2120
  NOTE
2121
    This function works correctly with utf8 or single-byte charset strings.
2122
    May fail with some multibyte charsets though.
2123
*/
2124
2125
void append_unescaped(String *res, const char *pos, uint length)
2126
{
2127
  const char *end= pos+length;
2128
  res->append('\'');
2129
2130
  for (; pos != end ; pos++)
2131
  {
2132
#if defined(USE_MB) && MYSQL_VERSION_ID < 40100
2133
    uint mblen;
2134
    if (use_mb(default_charset_info) &&
2135
        (mblen= my_ismbchar(default_charset_info, pos, end)))
2136
    {
2137
      res->append(pos, mblen);
2138
      pos+= mblen;
2139
      continue;
2140
    }
2141
#endif
2142
2143
    switch (*pos) {
2144
    case 0:				/* Must be escaped for 'mysql' */
2145
      res->append('\\');
2146
      res->append('0');
2147
      break;
2148
    case '\n':				/* Must be escaped for logs */
2149
      res->append('\\');
2150
      res->append('n');
2151
      break;
2152
    case '\r':
2153
      res->append('\\');		/* This gives better readability */
2154
      res->append('r');
2155
      break;
2156
    case '\\':
2157
      res->append('\\');		/* Because of the sql syntax */
2158
      res->append('\\');
2159
      break;
2160
    case '\'':
2161
      res->append('\'');		/* Because of the sql syntax */
2162
      res->append('\'');
2163
      break;
2164
    default:
2165
      res->append(*pos);
2166
      break;
2167
    }
2168
  }
2169
  res->append('\'');
2170
}
2171
2172
2173
	/* Create a .frm file */
2174
2175
File create_frm(THD *thd, const char *name, const char *db,
2176
                const char *table, uint reclength, uchar *fileinfo,
2177
  		HA_CREATE_INFO *create_info, uint keys, KEY *key_info)
2178
{
2179
  register File file;
2180
  ulong length;
2181
  uchar fill[IO_SIZE];
2182
  int create_flags= O_RDWR | O_TRUNC;
2183
  ulong key_comment_total_bytes= 0;
2184
  uint i;
2185
2186
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2187
    create_flags|= O_EXCL | O_NOFOLLOW;
2188
2189
  /* Fix this when we have new .frm files;  Current limit is 4G rows (QQ) */
2190
  if (create_info->max_rows > UINT_MAX32)
2191
    create_info->max_rows= UINT_MAX32;
2192
  if (create_info->min_rows > UINT_MAX32)
2193
    create_info->min_rows= UINT_MAX32;
2194
2195
  if ((file= my_create(name, CREATE_MODE, create_flags, MYF(0))) >= 0)
2196
  {
2197
    uint key_length, tmp_key_length;
2198
    uint tmp;
2199
    bzero((char*) fileinfo,64);
2200
    /* header */
2201
    fileinfo[0]=(uchar) 254;
2202
    fileinfo[1]= 1;
2203
    fileinfo[2]= FRM_VER+3+ test(create_info->varchar);
2204
2205
    fileinfo[3]= (uchar) ha_legacy_type(
2206
          ha_checktype(thd,ha_legacy_type(create_info->db_type),0,0));
2207
    fileinfo[4]=1;
2208
    int2store(fileinfo+6,IO_SIZE);		/* Next block starts here */
2209
    for (i= 0; i < keys; i++)
2210
    {
2211
      DBUG_ASSERT(test(key_info[i].flags & HA_USES_COMMENT) == 
2212
                 (key_info[i].comment.length > 0));
2213
      if (key_info[i].flags & HA_USES_COMMENT)
2214
        key_comment_total_bytes += 2 + key_info[i].comment.length;
2215
    }
2216
    /*
2217
      Keep in sync with pack_keys() in unireg.cc
2218
      For each key:
2219
      8 bytes for the key header
2220
      9 bytes for each key-part (MAX_REF_PARTS)
2221
      NAME_LEN bytes for the name
2222
      1 byte for the NAMES_SEP_CHAR (before the name)
2223
      For all keys:
2224
      6 bytes for the header
2225
      1 byte for the NAMES_SEP_CHAR (after the last name)
2226
      9 extra bytes (padding for safety? alignment?)
2227
      comments
2228
    */
2229
    key_length= (keys * (8 + MAX_REF_PARTS * 9 + NAME_LEN + 1) + 16 +
2230
                 key_comment_total_bytes);
2231
    length= next_io_size((ulong) (IO_SIZE+key_length+reclength+
2232
                                  create_info->extra_size));
2233
    int4store(fileinfo+10,length);
2234
    tmp_key_length= (key_length < 0xffff) ? key_length : 0xffff;
2235
    int2store(fileinfo+14,tmp_key_length);
2236
    int2store(fileinfo+16,reclength);
2237
    int4store(fileinfo+18,create_info->max_rows);
2238
    int4store(fileinfo+22,create_info->min_rows);
2239
    /* fileinfo[26] is set in mysql_create_frm() */
2240
    fileinfo[27]=2;				// Use long pack-fields
2241
    /* fileinfo[28 & 29] is set to key_info_length in mysql_create_frm() */
2242
    create_info->table_options|=HA_OPTION_LONG_BLOB_PTR; // Use portable blob pointers
2243
    int2store(fileinfo+30,create_info->table_options);
2244
    fileinfo[32]=0;				// No filename anymore
2245
    fileinfo[33]=5;                             // Mark for 5.0 frm file
2246
    int4store(fileinfo+34,create_info->avg_row_length);
2247
    fileinfo[38]= (create_info->default_table_charset ?
2248
		   create_info->default_table_charset->number : 0);
2249
    fileinfo[39]= (uchar) ((uint) create_info->transactional |
2250
                           ((uint) create_info->page_checksum << 2));
2251
    fileinfo[40]= (uchar) create_info->row_type;
2252
    /* Next few bytes where for RAID support */
2253
    fileinfo[41]= 0;
2254
    fileinfo[42]= 0;
2255
    fileinfo[43]= 0;
2256
    fileinfo[44]= 0;
2257
    fileinfo[45]= 0;
2258
    fileinfo[46]= 0;
2259
    int4store(fileinfo+47, key_length);
2260
    tmp= MYSQL_VERSION_ID;          // Store to avoid warning from int4store
2261
    int4store(fileinfo+51, tmp);
2262
    int4store(fileinfo+55, create_info->extra_size);
2263
    /*
2264
      59-60 is reserved for extra_rec_buf_length,
2265
      61 for default_part_db_type
2266
    */
2267
    int2store(fileinfo+62, create_info->key_block_size);
2268
    bzero(fill,IO_SIZE);
2269
    for (; length > IO_SIZE ; length-= IO_SIZE)
2270
    {
2271
      if (my_write(file,fill, IO_SIZE, MYF(MY_WME | MY_NABP)))
2272
      {
2273
	VOID(my_close(file,MYF(0)));
2274
	VOID(my_delete(name,MYF(0)));
2275
	return(-1);
2276
      }
2277
    }
2278
  }
2279
  else
2280
  {
2281
    if (my_errno == ENOENT)
2282
      my_error(ER_BAD_DB_ERROR,MYF(0),db);
2283
    else
2284
      my_error(ER_CANT_CREATE_TABLE,MYF(0),table,my_errno);
2285
  }
2286
  return (file);
2287
} /* create_frm */
2288
2289
2290
void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table)
2291
{
2292
  TABLE_SHARE *share= table->s;
2293
  DBUG_ENTER("update_create_info_from_table");
2294
2295
  create_info->max_rows= share->max_rows;
2296
  create_info->min_rows= share->min_rows;
2297
  create_info->table_options= share->db_create_options;
2298
  create_info->avg_row_length= share->avg_row_length;
2299
  create_info->row_type= share->row_type;
2300
  create_info->default_storage_media= share->default_storage_media;
2301
  create_info->tablespace= share->tablespace;
2302
  create_info->default_table_charset= share->table_charset;
2303
  create_info->table_charset= 0;
2304
  create_info->comment= share->comment;
2305
2306
  DBUG_VOID_RETURN;
2307
}
2308
2309
int
2310
rename_file_ext(const char * from,const char * to,const char * ext)
2311
{
2312
  char from_b[FN_REFLEN],to_b[FN_REFLEN];
2313
  VOID(strxmov(from_b,from,ext,NullS));
2314
  VOID(strxmov(to_b,to,ext,NullS));
2315
  return (my_rename(from_b,to_b,MYF(MY_WME)));
2316
}
2317
2318
2319
/*
2320
  Allocate string field in MEM_ROOT and return it as String
2321
2322
  SYNOPSIS
2323
    get_field()
2324
    mem   	MEM_ROOT for allocating
2325
    field 	Field for retrieving of string
2326
    res         result String
2327
2328
  RETURN VALUES
2329
    1   string is empty
2330
    0	all ok
2331
*/
2332
2333
bool get_field(MEM_ROOT *mem, Field *field, String *res)
2334
{
2335
  char buff[MAX_FIELD_WIDTH], *to;
2336
  String str(buff,sizeof(buff),&my_charset_bin);
2337
  uint length;
2338
2339
  field->val_str(&str);
2340
  if (!(length= str.length()))
2341
  {
2342
    res->length(0);
2343
    return 1;
2344
  }
2345
  if (!(to= strmake_root(mem, str.ptr(), length)))
2346
    length= 0;                                  // Safety fix
2347
  res->set(to, length, ((Field_str*)field)->charset());
2348
  return 0;
2349
}
2350
2351
2352
/*
2353
  Allocate string field in MEM_ROOT and return it as NULL-terminated string
2354
2355
  SYNOPSIS
2356
    get_field()
2357
    mem   	MEM_ROOT for allocating
2358
    field 	Field for retrieving of string
2359
2360
  RETURN VALUES
2361
    NullS  string is empty
2362
    #      pointer to NULL-terminated string value of field
2363
*/
2364
2365
char *get_field(MEM_ROOT *mem, Field *field)
2366
{
2367
  char buff[MAX_FIELD_WIDTH], *to;
2368
  String str(buff,sizeof(buff),&my_charset_bin);
2369
  uint length;
2370
2371
  field->val_str(&str);
2372
  length= str.length();
2373
  if (!length || !(to= (char*) alloc_root(mem,length+1)))
2374
    return NullS;
2375
  memcpy(to,str.ptr(),(uint) length);
2376
  to[length]=0;
2377
  return to;
2378
}
2379
2380
/*
2381
  DESCRIPTION
2382
    given a buffer with a key value, and a map of keyparts
2383
    that are present in this value, returns the length of the value
2384
*/
2385
uint calculate_key_len(TABLE *table, uint key, const uchar *buf,
2386
                       key_part_map keypart_map)
2387
{
2388
  /* works only with key prefixes */
2389
  DBUG_ASSERT(((keypart_map + 1) & keypart_map) == 0);
2390
2391
  KEY *key_info= table->s->key_info+key;
2392
  KEY_PART_INFO *key_part= key_info->key_part;
2393
  KEY_PART_INFO *end_key_part= key_part + key_info->key_parts;
2394
  uint length= 0;
2395
2396
  while (key_part < end_key_part && keypart_map)
2397
  {
2398
    length+= key_part->store_length;
2399
    keypart_map >>= 1;
2400
    key_part++;
2401
  }
2402
  return length;
2403
}
2404
2405
/*
2406
  Check if database name is valid
2407
2408
  SYNPOSIS
2409
    check_db_name()
2410
    org_name		Name of database and length
2411
2412
  NOTES
2413
    If lower_case_table_names is set then database is converted to lower case
2414
2415
  RETURN
2416
    0	ok
2417
    1   error
2418
*/
2419
2420
bool check_db_name(LEX_STRING *org_name)
2421
{
2422
  char *name= org_name->str;
2423
  uint name_length= org_name->length;
2424
2425
  if (!name_length || name_length > NAME_LEN || name[name_length - 1] == ' ')
2426
    return 1;
2427
2428
  if (lower_case_table_names && name != any_db)
2429
    my_casedn_str(files_charset_info, name);
2430
2431
  return check_identifier_name(org_name);
2432
}
2433
2434
2435
/*
2436
  Allow anything as a table name, as long as it doesn't contain an
2437
  ' ' at the end
2438
  returns 1 on error
2439
*/
2440
2441
2442
bool check_table_name(const char *name, uint length)
2443
{
2444
  if (!length || length > NAME_LEN || name[length - 1] == ' ')
2445
    return 1;
2446
  LEX_STRING ident;
2447
  ident.str= (char*) name;
2448
  ident.length= length;
2449
  return check_identifier_name(&ident);
2450
}
2451
2452
2453
/*
2454
  Eventually, a "length" argument should be added
2455
  to this function, and the inner loop changed to
2456
  check_identifier_name() call.
2457
*/
2458
bool check_column_name(const char *name)
2459
{
2460
  uint name_length= 0;  // name length in symbols
2461
  bool last_char_is_space= TRUE;
2462
  
2463
  while (*name)
2464
  {
2465
#if defined(USE_MB) && defined(USE_MB_IDENT)
2466
    last_char_is_space= my_isspace(system_charset_info, *name);
2467
    if (use_mb(system_charset_info))
2468
    {
2469
      int len=my_ismbchar(system_charset_info, name, 
2470
                          name+system_charset_info->mbmaxlen);
2471
      if (len)
2472
      {
2473
        if (len > 3) /* Disallow non-BMP characters */
2474
          return 1;
2475
        name += len;
2476
        name_length++;
2477
        continue;
2478
      }
2479
    }
2480
#else
2481
    last_char_is_space= *name==' ';
2482
#endif
2483
    /*
2484
      NAMES_SEP_CHAR is used in FRM format to separate SET and ENUM values.
2485
      It is defined as 0xFF, which is a not valid byte in utf8.
2486
      This assert is to catch use of this byte if we decide to
2487
      use non-utf8 as system_character_set.
2488
    */
2489
    DBUG_ASSERT(*name != NAMES_SEP_CHAR);
2490
    name++;
2491
    name_length++;
2492
  }
2493
  /* Error if empty or too long column name */
2494
  return last_char_is_space || (uint) name_length > NAME_CHAR_LEN;
2495
}
2496
2497
2498
/**
2499
  Checks whether a table is intact. Should be done *just* after the table has
2500
  been opened.
2501
2502
  @param[in] table             The table to check
2503
  @param[in] table_f_count     Expected number of columns in the table
2504
  @param[in] table_def         Expected structure of the table (column name
2505
                               and type)
2506
2507
  @retval  FALSE  OK
2508
  @retval  TRUE   There was an error. An error message is output
2509
                  to the error log.  We do not push an error
2510
                  message into the error stack because this
2511
                  function is currently only called at start up,
2512
                  and such errors never reach the user.
2513
*/
2514
2515
my_bool
2516
table_check_intact(TABLE *table, const uint table_f_count,
2517
                   const TABLE_FIELD_W_TYPE *table_def)
2518
{
2519
  uint i;
2520
  my_bool error= FALSE;
2521
  my_bool fields_diff_count;
2522
  DBUG_ENTER("table_check_intact");
2523
  DBUG_PRINT("info",("table: %s  expected_count: %d",
2524
                     table->alias, table_f_count));
2525
2526
  fields_diff_count= (table->s->fields != table_f_count);
2527
  if (fields_diff_count)
2528
  {
2529
    DBUG_PRINT("info", ("Column count has changed, checking the definition"));
2530
2531
    /* previous MySQL version */
2532
    if (MYSQL_VERSION_ID > table->s->mysql_version)
2533
    {
2534
      sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE),
2535
                      table->alias, table_f_count, table->s->fields,
2536
                      table->s->mysql_version, MYSQL_VERSION_ID);
2537
      DBUG_RETURN(TRUE);
2538
    }
2539
    else if (MYSQL_VERSION_ID == table->s->mysql_version)
2540
    {
2541
      sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), table->alias,
2542
                      table_f_count, table->s->fields);
2543
      DBUG_RETURN(TRUE);
2544
    }
2545
    /*
2546
      Something has definitely changed, but we're running an older
2547
      version of MySQL with new system tables.
2548
      Let's check column definitions. If a column was added at
2549
      the end of the table, then we don't care much since such change
2550
      is backward compatible.
2551
    */
2552
  }
2553
  char buffer[STRING_BUFFER_USUAL_SIZE];
2554
  for (i=0 ; i < table_f_count; i++, table_def++)
2555
  {
2556
    String sql_type(buffer, sizeof(buffer), system_charset_info);
2557
    sql_type.length(0);
2558
    if (i < table->s->fields)
2559
    {
2560
      Field *field= table->field[i];
2561
2562
      if (strncmp(field->field_name, table_def->name.str,
2563
                  table_def->name.length))
2564
      {
2565
        /*
2566
          Name changes are not fatal, we use ordinal numbers to access columns.
2567
          Still this can be a sign of a tampered table, output an error
2568
          to the error log.
2569
        */
2570
        sql_print_error("Incorrect definition of table %s.%s: "
2571
                        "expected column '%s' at position %d, found '%s'.",
2572
                        table->s->db.str, table->alias, table_def->name.str, i,
2573
                        field->field_name);
2574
      }
2575
      field->sql_type(sql_type);
2576
      /*
2577
        Generally, if column types don't match, then something is
2578
        wrong.
2579
2580
        However, we only compare column definitions up to the
2581
        length of the original definition, since we consider the
2582
        following definitions compatible:
2583
2584
        1. DATETIME and DATETIM
2585
        2. INT(11) and INT(11
2586
        3. SET('one', 'two') and SET('one', 'two', 'more')
2587
2588
        For SETs or ENUMs, if the same prefix is there it's OK to
2589
        add more elements - they will get higher ordinal numbers and
2590
        the new table definition is backward compatible with the
2591
        original one.
2592
       */
2593
      if (strncmp(sql_type.c_ptr_safe(), table_def->type.str,
2594
                  table_def->type.length - 1))
2595
      {
2596
        sql_print_error("Incorrect definition of table %s.%s: "
2597
                        "expected column '%s' at position %d to have type "
2598
                        "%s, found type %s.", table->s->db.str, table->alias,
2599
                        table_def->name.str, i, table_def->type.str,
2600
                        sql_type.c_ptr_safe());
2601
        error= TRUE;
2602
      }
2603
      else if (table_def->cset.str && !field->has_charset())
2604
      {
2605
        sql_print_error("Incorrect definition of table %s.%s: "
2606
                        "expected the type of column '%s' at position %d "
2607
                        "to have character set '%s' but the type has no "
2608
                        "character set.", table->s->db.str, table->alias,
2609
                        table_def->name.str, i, table_def->cset.str);
2610
        error= TRUE;
2611
      }
2612
      else if (table_def->cset.str &&
2613
               strcmp(field->charset()->csname, table_def->cset.str))
2614
      {
2615
        sql_print_error("Incorrect definition of table %s.%s: "
2616
                        "expected the type of column '%s' at position %d "
2617
                        "to have character set '%s' but found "
2618
                        "character set '%s'.", table->s->db.str, table->alias,
2619
                        table_def->name.str, i, table_def->cset.str,
2620
                        field->charset()->csname);
2621
        error= TRUE;
2622
      }
2623
    }
2624
    else
2625
    {
2626
      sql_print_error("Incorrect definition of table %s.%s: "
2627
                      "expected column '%s' at position %d to have type %s "
2628
                      " but the column is not found.",
2629
                      table->s->db.str, table->alias,
2630
                      table_def->name.str, i, table_def->type.str);
2631
      error= TRUE;
2632
    }
2633
  }
2634
  DBUG_RETURN(error);
2635
}
2636
2637
2638
/*
2639
  Create Item_field for each column in the table.
2640
2641
  SYNPOSIS
2642
    st_table::fill_item_list()
2643
      item_list          a pointer to an empty list used to store items
2644
2645
  DESCRIPTION
2646
    Create Item_field object for each column in the table and
2647
    initialize it with the corresponding Field. New items are
2648
    created in the current THD memory root.
2649
2650
  RETURN VALUE
2651
    0                    success
2652
    1                    out of memory
2653
*/
2654
2655
bool st_table::fill_item_list(List<Item> *item_list) const
2656
{
2657
  /*
2658
    All Item_field's created using a direct pointer to a field
2659
    are fixed in Item_field constructor.
2660
  */
2661
  for (Field **ptr= field; *ptr; ptr++)
2662
  {
2663
    Item_field *item= new Item_field(*ptr);
2664
    if (!item || item_list->push_back(item))
2665
      return TRUE;
2666
  }
2667
  return FALSE;
2668
}
2669
2670
/*
2671
  Reset an existing list of Item_field items to point to the
2672
  Fields of this table.
2673
2674
  SYNPOSIS
2675
    st_table::fill_item_list()
2676
      item_list          a non-empty list with Item_fields
2677
2678
  DESCRIPTION
2679
    This is a counterpart of fill_item_list used to redirect
2680
    Item_fields to the fields of a newly created table.
2681
    The caller must ensure that number of items in the item_list
2682
    is the same as the number of columns in the table.
2683
*/
2684
2685
void st_table::reset_item_list(List<Item> *item_list) const
2686
{
2687
  List_iterator_fast<Item> it(*item_list);
2688
  for (Field **ptr= field; *ptr; ptr++)
2689
  {
2690
    Item_field *item_field= (Item_field*) it++;
2691
    DBUG_ASSERT(item_field != 0);
2692
    item_field->reset_field(*ptr);
2693
  }
2694
}
2695
2696
2697
/*
2698
  Merge ON expressions for a view
2699
2700
  SYNOPSIS
2701
    merge_on_conds()
2702
    thd             thread handle
2703
    table           table for the VIEW
2704
    is_cascaded     TRUE <=> merge ON expressions from underlying views
2705
2706
  DESCRIPTION
2707
    This function returns the result of ANDing the ON expressions
2708
    of the given view and all underlying views. The ON expressions
2709
    of the underlying views are added only if is_cascaded is TRUE.
2710
2711
  RETURN
2712
    Pointer to the built expression if there is any.
2713
    Otherwise and in the case of a failure NULL is returned.
2714
*/
2715
2716
static Item *
2717
merge_on_conds(THD *thd, TABLE_LIST *table, bool is_cascaded)
2718
{
2719
  DBUG_ENTER("merge_on_conds");
2720
2721
  Item *cond= NULL;
2722
  DBUG_PRINT("info", ("alias: %s", table->alias));
2723
  if (table->on_expr)
2724
    cond= table->on_expr->copy_andor_structure(thd);
2725
  if (!table->nested_join)
2726
    DBUG_RETURN(cond);
2727
  List_iterator<TABLE_LIST> li(table->nested_join->join_list);
2728
  while (TABLE_LIST *tbl= li++)
2729
  {
2730
    cond= and_conds(cond, merge_on_conds(thd, tbl, is_cascaded));
2731
  }
2732
  DBUG_RETURN(cond);
2733
}
2734
2735
2736
/*
2737
  Find underlying base tables (TABLE_LIST) which represent given
2738
  table_to_find (TABLE)
2739
2740
  SYNOPSIS
2741
    TABLE_LIST::find_underlying_table()
2742
    table_to_find table to find
2743
2744
  RETURN
2745
    0  table is not found
2746
    found table reference
2747
*/
2748
2749
TABLE_LIST *TABLE_LIST::find_underlying_table(TABLE *table_to_find)
2750
{
2751
  /* is this real table and table which we are looking for? */
2752
  if (table == table_to_find && merge_underlying_list == 0)
2753
    return this;
2754
2755
  for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local)
2756
  {
2757
    TABLE_LIST *result;
2758
    if ((result= tbl->find_underlying_table(table_to_find)))
2759
      return result;
2760
  }
2761
  return 0;
2762
}
2763
2764
/*
2765
  cleunup items belonged to view fields translation table
2766
2767
  SYNOPSIS
2768
    TABLE_LIST::cleanup_items()
2769
*/
2770
2771
void TABLE_LIST::cleanup_items()
2772
{
2773
  if (!field_translation)
2774
    return;
2775
2776
  for (Field_translator *transl= field_translation;
2777
       transl < field_translation_end;
2778
       transl++)
2779
    transl->item->walk(&Item::cleanup_processor, 0, 0);
2780
}
2781
2782
2783
/*
2784
  Set insert_values buffer
2785
2786
  SYNOPSIS
2787
    set_insert_values()
2788
    mem_root   memory pool for allocating
2789
2790
  RETURN
2791
    FALSE - OK
2792
    TRUE  - out of memory
2793
*/
2794
2795
bool TABLE_LIST::set_insert_values(MEM_ROOT *mem_root)
2796
{
2797
  if (table)
2798
  {
2799
    if (!table->insert_values &&
2800
        !(table->insert_values= (uchar *)alloc_root(mem_root,
2801
                                                   table->s->rec_buff_length)))
2802
      return TRUE;
2803
  }
2804
2805
  return FALSE;
2806
}
2807
2808
2809
/*
2810
  Test if this is a leaf with respect to name resolution.
2811
2812
  SYNOPSIS
2813
    TABLE_LIST::is_leaf_for_name_resolution()
2814
2815
  DESCRIPTION
2816
    A table reference is a leaf with respect to name resolution if
2817
    it is either a leaf node in a nested join tree (table, view,
2818
    schema table, subquery), or an inner node that represents a
2819
    NATURAL/USING join, or a nested join with materialized join
2820
    columns.
2821
2822
  RETURN
2823
    TRUE if a leaf, FALSE otherwise.
2824
*/
2825
bool TABLE_LIST::is_leaf_for_name_resolution()
2826
{
2827
  return (is_natural_join || is_join_columns_complete || !nested_join);
2828
}
2829
2830
2831
/*
2832
  Retrieve the first (left-most) leaf in a nested join tree with
2833
  respect to name resolution.
2834
2835
  SYNOPSIS
2836
    TABLE_LIST::first_leaf_for_name_resolution()
2837
2838
  DESCRIPTION
2839
    Given that 'this' is a nested table reference, recursively walk
2840
    down the left-most children of 'this' until we reach a leaf
2841
    table reference with respect to name resolution.
2842
2843
  IMPLEMENTATION
2844
    The left-most child of a nested table reference is the last element
2845
    in the list of children because the children are inserted in
2846
    reverse order.
2847
2848
  RETURN
2849
    If 'this' is a nested table reference - the left-most child of
2850
      the tree rooted in 'this',
2851
    else return 'this'
2852
*/
2853
2854
TABLE_LIST *TABLE_LIST::first_leaf_for_name_resolution()
2855
{
2856
  TABLE_LIST *cur_table_ref;
2857
  NESTED_JOIN *cur_nested_join;
2858
2859
  if (is_leaf_for_name_resolution())
2860
    return this;
2861
  DBUG_ASSERT(nested_join);
2862
2863
  for (cur_nested_join= nested_join;
2864
       cur_nested_join;
2865
       cur_nested_join= cur_table_ref->nested_join)
2866
  {
2867
    List_iterator_fast<TABLE_LIST> it(cur_nested_join->join_list);
2868
    cur_table_ref= it++;
2869
    /*
2870
      If the current nested join is a RIGHT JOIN, the operands in
2871
      'join_list' are in reverse order, thus the first operand is
2872
      already at the front of the list. Otherwise the first operand
2873
      is in the end of the list of join operands.
2874
    */
2875
    if (!(cur_table_ref->outer_join & JOIN_TYPE_RIGHT))
2876
    {
2877
      TABLE_LIST *next;
2878
      while ((next= it++))
2879
        cur_table_ref= next;
2880
    }
2881
    if (cur_table_ref->is_leaf_for_name_resolution())
2882
      break;
2883
  }
2884
  return cur_table_ref;
2885
}
2886
2887
2888
/*
2889
  Retrieve the last (right-most) leaf in a nested join tree with
2890
  respect to name resolution.
2891
2892
  SYNOPSIS
2893
    TABLE_LIST::last_leaf_for_name_resolution()
2894
2895
  DESCRIPTION
2896
    Given that 'this' is a nested table reference, recursively walk
2897
    down the right-most children of 'this' until we reach a leaf
2898
    table reference with respect to name resolution.
2899
2900
  IMPLEMENTATION
2901
    The right-most child of a nested table reference is the first
2902
    element in the list of children because the children are inserted
2903
    in reverse order.
2904
2905
  RETURN
2906
    - If 'this' is a nested table reference - the right-most child of
2907
      the tree rooted in 'this',
2908
    - else - 'this'
2909
*/
2910
2911
TABLE_LIST *TABLE_LIST::last_leaf_for_name_resolution()
2912
{
2913
  TABLE_LIST *cur_table_ref= this;
2914
  NESTED_JOIN *cur_nested_join;
2915
2916
  if (is_leaf_for_name_resolution())
2917
    return this;
2918
  DBUG_ASSERT(nested_join);
2919
2920
  for (cur_nested_join= nested_join;
2921
       cur_nested_join;
2922
       cur_nested_join= cur_table_ref->nested_join)
2923
  {
2924
    cur_table_ref= cur_nested_join->join_list.head();
2925
    /*
2926
      If the current nested is a RIGHT JOIN, the operands in
2927
      'join_list' are in reverse order, thus the last operand is in the
2928
      end of the list.
2929
    */
2930
    if ((cur_table_ref->outer_join & JOIN_TYPE_RIGHT))
2931
    {
2932
      List_iterator_fast<TABLE_LIST> it(cur_nested_join->join_list);
2933
      TABLE_LIST *next;
2934
      cur_table_ref= it++;
2935
      while ((next= it++))
2936
        cur_table_ref= next;
2937
    }
2938
    if (cur_table_ref->is_leaf_for_name_resolution())
2939
      break;
2940
  }
2941
  return cur_table_ref;
2942
}
2943
2944
2945
Natural_join_column::Natural_join_column(Field_translator *field_param,
2946
                                         TABLE_LIST *tab)
2947
{
2948
  DBUG_ASSERT(tab->field_translation);
2949
  view_field= field_param;
2950
  table_field= NULL;
2951
  table_ref= tab;
2952
  is_common= FALSE;
2953
}
2954
2955
2956
Natural_join_column::Natural_join_column(Field *field_param,
2957
                                         TABLE_LIST *tab)
2958
{
2959
  DBUG_ASSERT(tab->table == field_param->table);
2960
  table_field= field_param;
2961
  view_field= NULL;
2962
  table_ref= tab;
2963
  is_common= FALSE;
2964
}
2965
2966
2967
const char *Natural_join_column::name()
2968
{
2969
  if (view_field)
2970
  {
2971
    DBUG_ASSERT(table_field == NULL);
2972
    return view_field->name;
2973
  }
2974
2975
  return table_field->field_name;
2976
}
2977
2978
2979
Item *Natural_join_column::create_item(THD *thd)
2980
{
2981
  if (view_field)
2982
  {
2983
    DBUG_ASSERT(table_field == NULL);
2984
    return create_view_field(thd, table_ref, &view_field->item,
2985
                             view_field->name);
2986
  }
2987
  return new Item_field(thd, &thd->lex->current_select->context, table_field);
2988
}
2989
2990
2991
Field *Natural_join_column::field()
2992
{
2993
  if (view_field)
2994
  {
2995
    DBUG_ASSERT(table_field == NULL);
2996
    return NULL;
2997
  }
2998
  return table_field;
2999
}
3000
3001
3002
const char *Natural_join_column::table_name()
3003
{
3004
  DBUG_ASSERT(table_ref);
3005
  return table_ref->alias;
3006
}
3007
3008
3009
const char *Natural_join_column::db_name()
3010
{
3011
  /*
3012
    Test that TABLE_LIST::db is the same as st_table_share::db to
3013
    ensure consistency. An exception are I_S schema tables, which
3014
    are inconsistent in this respect.
3015
  */
3016
  DBUG_ASSERT(!strcmp(table_ref->db,
3017
                      table_ref->table->s->db.str) ||
3018
              (table_ref->schema_table &&
3019
               table_ref->table->s->db.str[0] == 0));
3020
  return table_ref->db;
3021
}
3022
3023
3024
void Field_iterator_view::set(TABLE_LIST *table)
3025
{
3026
  DBUG_ASSERT(table->field_translation);
3027
  view= table;
3028
  ptr= table->field_translation;
3029
  array_end= table->field_translation_end;
3030
}
3031
3032
3033
const char *Field_iterator_table::name()
3034
{
3035
  return (*ptr)->field_name;
3036
}
3037
3038
3039
Item *Field_iterator_table::create_item(THD *thd)
3040
{
3041
  SELECT_LEX *select= thd->lex->current_select;
3042
3043
  Item_field *item= new Item_field(thd, &select->context, *ptr);
3044
  if (item && thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
3045
      !thd->lex->in_sum_func && select->cur_pos_in_select_list != UNDEF_POS)
3046
  {
3047
    select->non_agg_fields.push_back(item);
3048
    item->marker= select->cur_pos_in_select_list;
3049
  }
3050
  return item;
3051
}
3052
3053
3054
const char *Field_iterator_view::name()
3055
{
3056
  return ptr->name;
3057
}
3058
3059
3060
Item *Field_iterator_view::create_item(THD *thd)
3061
{
3062
  return create_view_field(thd, view, &ptr->item, ptr->name);
3063
}
3064
3065
Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
3066
                        const char *name)
3067
{
3068
  DBUG_ENTER("create_view_field");
3069
  if (view->schema_table_reformed)
3070
  {
3071
    Item *field= *field_ref;
3072
3073
    /*
3074
      Translation table items are always Item_fields and already fixed
3075
      ('mysql_schema_table' function). So we can return directly the
3076
      field. This case happens only for 'show & where' commands.
3077
    */
3078
    DBUG_ASSERT(field && field->fixed);
3079
    DBUG_RETURN(field);
3080
  }
3081
3082
  DBUG_RETURN(NULL);
3083
}
3084
3085
3086
void Field_iterator_natural_join::set(TABLE_LIST *table_ref)
3087
{
3088
  DBUG_ASSERT(table_ref->join_columns);
3089
  column_ref_it.init(*(table_ref->join_columns));
3090
  cur_column_ref= column_ref_it++;
3091
}
3092
3093
3094
void Field_iterator_natural_join::next()
3095
{
3096
  cur_column_ref= column_ref_it++;
3097
  DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field ||
3098
              cur_column_ref->table_ref->table ==
3099
              cur_column_ref->table_field->table);
3100
}
3101
3102
3103
void Field_iterator_table_ref::set_field_iterator()
3104
{
3105
  DBUG_ENTER("Field_iterator_table_ref::set_field_iterator");
3106
  /*
3107
    If the table reference we are iterating over is a natural join, or it is
3108
    an operand of a natural join, and TABLE_LIST::join_columns contains all
3109
    the columns of the join operand, then we pick the columns from
3110
    TABLE_LIST::join_columns, instead of the  orginial container of the
3111
    columns of the join operator.
3112
  */
3113
  if (table_ref->is_join_columns_complete)
3114
  {
3115
    /* Necesary, but insufficient conditions. */
3116
    DBUG_ASSERT(table_ref->is_natural_join ||
3117
                table_ref->nested_join ||
3118
                table_ref->join_columns &&
3119
                /* This is a merge view. */
3120
                ((table_ref->field_translation &&
3121
                  table_ref->join_columns->elements ==
3122
                  (ulong)(table_ref->field_translation_end -
3123
                          table_ref->field_translation)) ||
3124
                 /* This is stored table or a tmptable view. */
3125
                 (!table_ref->field_translation &&
3126
                  table_ref->join_columns->elements ==
3127
                  table_ref->table->s->fields)));
3128
    field_it= &natural_join_it;
3129
    DBUG_PRINT("info",("field_it for '%s' is Field_iterator_natural_join",
3130
                       table_ref->alias));
3131
  }
3132
  /* This is a base table or stored view. */
3133
  else
3134
  {
3135
    DBUG_ASSERT(table_ref->table);
3136
    field_it= &table_field_it;
3137
    DBUG_PRINT("info", ("field_it for '%s' is Field_iterator_table",
3138
                        table_ref->alias));
3139
  }
3140
  field_it->set(table_ref);
3141
  DBUG_VOID_RETURN;
3142
}
3143
3144
3145
void Field_iterator_table_ref::set(TABLE_LIST *table)
3146
{
3147
  DBUG_ASSERT(table);
3148
  first_leaf= table->first_leaf_for_name_resolution();
3149
  last_leaf=  table->last_leaf_for_name_resolution();
3150
  DBUG_ASSERT(first_leaf && last_leaf);
3151
  table_ref= first_leaf;
3152
  set_field_iterator();
3153
}
3154
3155
3156
void Field_iterator_table_ref::next()
3157
{
3158
  /* Move to the next field in the current table reference. */
3159
  field_it->next();
3160
  /*
3161
    If all fields of the current table reference are exhausted, move to
3162
    the next leaf table reference.
3163
  */
3164
  if (field_it->end_of_fields() && table_ref != last_leaf)
3165
  {
3166
    table_ref= table_ref->next_name_resolution_table;
3167
    DBUG_ASSERT(table_ref);
3168
    set_field_iterator();
3169
  }
3170
}
3171
3172
3173
const char *Field_iterator_table_ref::table_name()
3174
{
3175
  if (table_ref->is_natural_join)
3176
    return natural_join_it.column_ref()->table_name();
3177
3178
  DBUG_ASSERT(!strcmp(table_ref->table_name,
3179
                      table_ref->table->s->table_name.str));
3180
  return table_ref->table_name;
3181
}
3182
3183
3184
const char *Field_iterator_table_ref::db_name()
3185
{
3186
  if (table_ref->is_natural_join)
3187
    return natural_join_it.column_ref()->db_name();
3188
3189
  /*
3190
    Test that TABLE_LIST::db is the same as st_table_share::db to
3191
    ensure consistency. An exception are I_S schema tables, which
3192
    are inconsistent in this respect.
3193
  */
3194
  DBUG_ASSERT(!strcmp(table_ref->db, table_ref->table->s->db.str) ||
3195
              (table_ref->schema_table &&
3196
               table_ref->table->s->db.str[0] == 0));
3197
3198
  return table_ref->db;
3199
}
3200
3201
3202
/*
3203
  Create new or return existing column reference to a column of a
3204
  natural/using join.
3205
3206
  SYNOPSIS
3207
    Field_iterator_table_ref::get_or_create_column_ref()
3208
    parent_table_ref  the parent table reference over which the
3209
                      iterator is iterating
3210
3211
  DESCRIPTION
3212
    Create a new natural join column for the current field of the
3213
    iterator if no such column was created, or return an already
3214
    created natural join column. The former happens for base tables or
3215
    views, and the latter for natural/using joins. If a new field is
3216
    created, then the field is added to 'parent_table_ref' if it is
3217
    given, or to the original table referene of the field if
3218
    parent_table_ref == NULL.
3219
3220
  NOTES
3221
    This method is designed so that when a Field_iterator_table_ref
3222
    walks through the fields of a table reference, all its fields
3223
    are created and stored as follows:
3224
    - If the table reference being iterated is a stored table, view or
3225
      natural/using join, store all natural join columns in a list
3226
      attached to that table reference.
3227
    - If the table reference being iterated is a nested join that is
3228
      not natural/using join, then do not materialize its result
3229
      fields. This is OK because for such table references
3230
      Field_iterator_table_ref iterates over the fields of the nested
3231
      table references (recursively). In this way we avoid the storage
3232
      of unnecessay copies of result columns of nested joins.
3233
3234
  RETURN
3235
    #     Pointer to a column of a natural join (or its operand)
3236
    NULL  No memory to allocate the column
3237
*/
3238
3239
Natural_join_column *
3240
Field_iterator_table_ref::get_or_create_column_ref(TABLE_LIST *parent_table_ref)
3241
{
3242
  Natural_join_column *nj_col;
3243
  bool is_created= TRUE;
3244
  uint field_count;
3245
  TABLE_LIST *add_table_ref= parent_table_ref ?
3246
                             parent_table_ref : table_ref;
3247
3248
  if (field_it == &table_field_it)
3249
  {
3250
    /* The field belongs to a stored table. */
3251
    Field *tmp_field= table_field_it.field();
3252
    nj_col= new Natural_join_column(tmp_field, table_ref);
3253
    field_count= table_ref->table->s->fields;
3254
  }
3255
  else if (field_it == &view_field_it)
3256
  {
3257
    /* The field belongs to a merge view or information schema table. */
3258
    Field_translator *translated_field= view_field_it.field_translator();
3259
    nj_col= new Natural_join_column(translated_field, table_ref);
3260
    field_count= table_ref->field_translation_end -
3261
                 table_ref->field_translation;
3262
  }
3263
  else
3264
  {
3265
    /*
3266
      The field belongs to a NATURAL join, therefore the column reference was
3267
      already created via one of the two constructor calls above. In this case
3268
      we just return the already created column reference.
3269
    */
3270
    DBUG_ASSERT(table_ref->is_join_columns_complete);
3271
    is_created= FALSE;
3272
    nj_col= natural_join_it.column_ref();
3273
    DBUG_ASSERT(nj_col);
3274
  }
3275
  DBUG_ASSERT(!nj_col->table_field ||
3276
              nj_col->table_ref->table == nj_col->table_field->table);
3277
3278
  /*
3279
    If the natural join column was just created add it to the list of
3280
    natural join columns of either 'parent_table_ref' or to the table
3281
    reference that directly contains the original field.
3282
  */
3283
  if (is_created)
3284
  {
3285
    /* Make sure not all columns were materialized. */
3286
    DBUG_ASSERT(!add_table_ref->is_join_columns_complete);
3287
    if (!add_table_ref->join_columns)
3288
    {
3289
      /* Create a list of natural join columns on demand. */
3290
      if (!(add_table_ref->join_columns= new List<Natural_join_column>))
3291
        return NULL;
3292
      add_table_ref->is_join_columns_complete= FALSE;
3293
    }
3294
    add_table_ref->join_columns->push_back(nj_col);
3295
    /*
3296
      If new fields are added to their original table reference, mark if
3297
      all fields were added. We do it here as the caller has no easy way
3298
      of knowing when to do it.
3299
      If the fields are being added to parent_table_ref, then the caller
3300
      must take care to mark when all fields are created/added.
3301
    */
3302
    if (!parent_table_ref &&
3303
        add_table_ref->join_columns->elements == field_count)
3304
      add_table_ref->is_join_columns_complete= TRUE;
3305
  }
3306
3307
  return nj_col;
3308
}
3309
3310
3311
/*
3312
  Return an existing reference to a column of a natural/using join.
3313
3314
  SYNOPSIS
3315
    Field_iterator_table_ref::get_natural_column_ref()
3316
3317
  DESCRIPTION
3318
    The method should be called in contexts where it is expected that
3319
    all natural join columns are already created, and that the column
3320
    being retrieved is a Natural_join_column.
3321
3322
  RETURN
3323
    #     Pointer to a column of a natural join (or its operand)
3324
    NULL  No memory to allocate the column
3325
*/
3326
3327
Natural_join_column *
3328
Field_iterator_table_ref::get_natural_column_ref()
3329
{
3330
  Natural_join_column *nj_col;
3331
3332
  DBUG_ASSERT(field_it == &natural_join_it);
3333
  /*
3334
    The field belongs to a NATURAL join, therefore the column reference was
3335
    already created via one of the two constructor calls above. In this case
3336
    we just return the already created column reference.
3337
  */
3338
  nj_col= natural_join_it.column_ref();
3339
  DBUG_ASSERT(nj_col &&
3340
              (!nj_col->table_field ||
3341
               nj_col->table_ref->table == nj_col->table_field->table));
3342
  return nj_col;
3343
}
3344
3345
/*****************************************************************************
3346
  Functions to handle column usage bitmaps (read_set, write_set etc...)
3347
*****************************************************************************/
3348
3349
/* Reset all columns bitmaps */
3350
3351
void st_table::clear_column_bitmaps()
3352
{
3353
  /*
3354
    Reset column read/write usage. It's identical to:
3355
    bitmap_clear_all(&table->def_read_set);
3356
    bitmap_clear_all(&table->def_write_set);
3357
  */
3358
  bzero((char*) def_read_set.bitmap, s->column_bitmap_size*2);
3359
  column_bitmaps_set(&def_read_set, &def_write_set);
3360
}
3361
3362
3363
/*
3364
  Tell handler we are going to call position() and rnd_pos() later.
3365
  
3366
  NOTES:
3367
  This is needed for handlers that uses the primary key to find the
3368
  row. In this case we have to extend the read bitmap with the primary
3369
  key fields.
3370
*/
3371
3372
void st_table::prepare_for_position()
3373
{
3374
  DBUG_ENTER("st_table::prepare_for_position");
3375
3376
  if ((file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
3377
      s->primary_key < MAX_KEY)
3378
  {
3379
    mark_columns_used_by_index_no_reset(s->primary_key, read_set);
3380
    /* signal change */
3381
    file->column_bitmaps_signal();
3382
  }
3383
  DBUG_VOID_RETURN;
3384
}
3385
3386
3387
/*
3388
  Mark that only fields from one key is used
3389
3390
  NOTE:
3391
    This changes the bitmap to use the tmp bitmap
3392
    After this, you can't access any other columns in the table until
3393
    bitmaps are reset, for example with st_table::clear_column_bitmaps()
3394
    or st_table::restore_column_maps_after_mark_index()
3395
*/
3396
3397
void st_table::mark_columns_used_by_index(uint index)
3398
{
3399
  MY_BITMAP *bitmap= &tmp_set;
3400
  DBUG_ENTER("st_table::mark_columns_used_by_index");
3401
3402
  (void) file->extra(HA_EXTRA_KEYREAD);
3403
  bitmap_clear_all(bitmap);
3404
  mark_columns_used_by_index_no_reset(index, bitmap);
3405
  column_bitmaps_set(bitmap, bitmap);
3406
  DBUG_VOID_RETURN;
3407
}
3408
3409
3410
/*
3411
  Restore to use normal column maps after key read
3412
3413
  NOTES
3414
    This reverse the change done by mark_columns_used_by_index
3415
3416
  WARNING
3417
    For this to work, one must have the normal table maps in place
3418
    when calling mark_columns_used_by_index
3419
*/
3420
3421
void st_table::restore_column_maps_after_mark_index()
3422
{
3423
  DBUG_ENTER("st_table::restore_column_maps_after_mark_index");
3424
3425
  key_read= 0;
3426
  (void) file->extra(HA_EXTRA_NO_KEYREAD);
3427
  default_column_bitmaps();
3428
  file->column_bitmaps_signal();
3429
  DBUG_VOID_RETURN;
3430
}
3431
3432
3433
/*
3434
  mark columns used by key, but don't reset other fields
3435
*/
3436
3437
void st_table::mark_columns_used_by_index_no_reset(uint index,
3438
                                                   MY_BITMAP *bitmap)
3439
{
3440
  KEY_PART_INFO *key_part= key_info[index].key_part;
3441
  KEY_PART_INFO *key_part_end= (key_part +
3442
                                key_info[index].key_parts);
3443
  for (;key_part != key_part_end; key_part++)
3444
    bitmap_set_bit(bitmap, key_part->fieldnr-1);
3445
}
3446
3447
3448
/*
3449
  Mark auto-increment fields as used fields in both read and write maps
3450
3451
  NOTES
3452
    This is needed in insert & update as the auto-increment field is
3453
    always set and sometimes read.
3454
*/
3455
3456
void st_table::mark_auto_increment_column()
3457
{
3458
  DBUG_ASSERT(found_next_number_field);
3459
  /*
3460
    We must set bit in read set as update_auto_increment() is using the
3461
    store() to check overflow of auto_increment values
3462
  */
3463
  bitmap_set_bit(read_set, found_next_number_field->field_index);
3464
  bitmap_set_bit(write_set, found_next_number_field->field_index);
3465
  if (s->next_number_keypart)
3466
    mark_columns_used_by_index_no_reset(s->next_number_index, read_set);
3467
  file->column_bitmaps_signal();
3468
}
3469
3470
3471
/*
3472
  Mark columns needed for doing an delete of a row
3473
3474
  DESCRIPTON
3475
    Some table engines don't have a cursor on the retrieve rows
3476
    so they need either to use the primary key or all columns to
3477
    be able to delete a row.
3478
3479
    If the engine needs this, the function works as follows:
3480
    - If primary key exits, mark the primary key columns to be read.
3481
    - If not, mark all columns to be read
3482
3483
    If the engine has HA_REQUIRES_KEY_COLUMNS_FOR_DELETE, we will
3484
    mark all key columns as 'to-be-read'. This allows the engine to
3485
    loop over the given record to find all keys and doesn't have to
3486
    retrieve the row again.
3487
*/
3488
3489
void st_table::mark_columns_needed_for_delete()
3490
{
3491
  if (file->ha_table_flags() & HA_REQUIRES_KEY_COLUMNS_FOR_DELETE)
3492
  {
3493
    Field **reg_field;
3494
    for (reg_field= field ; *reg_field ; reg_field++)
3495
    {
3496
      if ((*reg_field)->flags & PART_KEY_FLAG)
3497
        bitmap_set_bit(read_set, (*reg_field)->field_index);
3498
    }
3499
    file->column_bitmaps_signal();
3500
  }
3501
  if (file->ha_table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_DELETE ||
3502
      (mysql_bin_log.is_open() && in_use && in_use->current_stmt_binlog_row_based))
3503
  {
3504
    /*
3505
      If the handler has no cursor capabilites, or we have row-based
3506
      replication active for the current statement, we have to read
3507
      either the primary key, the hidden primary key or all columns to
3508
      be able to do an delete
3509
    */
3510
    if (s->primary_key == MAX_KEY)
3511
      file->use_hidden_primary_key();
3512
    else
3513
    {
3514
      mark_columns_used_by_index_no_reset(s->primary_key, read_set);
3515
      file->column_bitmaps_signal();
3516
    }
3517
  }
3518
}
3519
3520
3521
/*
3522
  Mark columns needed for doing an update of a row
3523
3524
  DESCRIPTON
3525
    Some engines needs to have all columns in an update (to be able to
3526
    build a complete row). If this is the case, we mark all not
3527
    updated columns to be read.
3528
3529
    If this is no the case, we do like in the delete case and mark
3530
    if neeed, either the primary key column or all columns to be read.
3531
    (see mark_columns_needed_for_delete() for details)
3532
3533
    If the engine has HA_REQUIRES_KEY_COLUMNS_FOR_DELETE, we will
3534
    mark all USED key columns as 'to-be-read'. This allows the engine to
3535
    loop over the given record to find all changed keys and doesn't have to
3536
    retrieve the row again.
3537
*/
3538
3539
void st_table::mark_columns_needed_for_update()
3540
{
3541
  DBUG_ENTER("mark_columns_needed_for_update");
3542
  if (file->ha_table_flags() & HA_REQUIRES_KEY_COLUMNS_FOR_DELETE)
3543
  {
3544
    /* Mark all used key columns for read */
3545
    Field **reg_field;
3546
    for (reg_field= field ; *reg_field ; reg_field++)
3547
    {
3548
      /* Merge keys is all keys that had a column refered to in the query */
3549
      if (merge_keys.is_overlapping((*reg_field)->part_of_key))
3550
        bitmap_set_bit(read_set, (*reg_field)->field_index);
3551
    }
3552
    file->column_bitmaps_signal();
3553
  }
3554
  if ((file->ha_table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) ||
3555
      (mysql_bin_log.is_open() && in_use && in_use->current_stmt_binlog_row_based))
3556
  {
3557
    /*
3558
      If the handler has no cursor capabilites, or we have row-based
3559
      logging active for the current statement, we have to read either
3560
      the primary key, the hidden primary key or all columns to be
3561
      able to do an update
3562
    */
3563
    if (s->primary_key == MAX_KEY)
3564
      file->use_hidden_primary_key();
3565
    else
3566
    {
3567
      mark_columns_used_by_index_no_reset(s->primary_key, read_set);
3568
      file->column_bitmaps_signal();
3569
    }
3570
  }
3571
  DBUG_VOID_RETURN;
3572
}
3573
3574
3575
/*
3576
  Mark columns the handler needs for doing an insert
3577
3578
  For now, this is used to mark fields used by the trigger
3579
  as changed.
3580
*/
3581
3582
void st_table::mark_columns_needed_for_insert()
3583
{
3584
  if (found_next_number_field)
3585
    mark_auto_increment_column();
3586
}
3587
3588
/*
3589
  Cleanup this table for re-execution.
3590
3591
  SYNOPSIS
3592
    TABLE_LIST::reinit_before_use()
3593
*/
3594
3595
void TABLE_LIST::reinit_before_use(THD *thd)
3596
{
3597
  /*
3598
    Reset old pointers to TABLEs: they are not valid since the tables
3599
    were closed in the end of previous prepare or execute call.
3600
  */
3601
  table= 0;
3602
  /* Reset is_schema_table_processed value(needed for I_S tables */
3603
  schema_table_state= NOT_PROCESSED;
3604
3605
  TABLE_LIST *embedded; /* The table at the current level of nesting. */
3606
  TABLE_LIST *parent_embedding= this; /* The parent nested table reference. */
3607
  do
3608
  {
3609
    embedded= parent_embedding;
3610
    if (embedded->prep_on_expr)
3611
      embedded->on_expr= embedded->prep_on_expr->copy_andor_structure(thd);
3612
    parent_embedding= embedded->embedding;
3613
  }
3614
  while (parent_embedding &&
3615
         parent_embedding->nested_join->join_list.head() == embedded);
3616
}
3617
3618
/*
3619
  Return subselect that contains the FROM list this table is taken from
3620
3621
  SYNOPSIS
3622
    TABLE_LIST::containing_subselect()
3623
 
3624
  RETURN
3625
    Subselect item for the subquery that contains the FROM list
3626
    this table is taken from if there is any
3627
    0 - otherwise
3628
3629
*/
3630
3631
Item_subselect *TABLE_LIST::containing_subselect()
3632
{    
3633
  return (select_lex ? select_lex->master_unit()->item : 0);
3634
}
3635
3636
/*
3637
  Compiles the tagged hints list and fills up the bitmasks.
3638
3639
  SYNOPSIS
3640
    process_index_hints()
3641
      table         the TABLE to operate on.
3642
3643
  DESCRIPTION
3644
    The parser collects the index hints for each table in a "tagged list" 
3645
    (TABLE_LIST::index_hints). Using the information in this tagged list
3646
    this function sets the members st_table::keys_in_use_for_query, 
3647
    st_table::keys_in_use_for_group_by, st_table::keys_in_use_for_order_by,
3648
    st_table::force_index and st_table::covering_keys.
3649
3650
    Current implementation of the runtime does not allow mixing FORCE INDEX
3651
    and USE INDEX, so this is checked here. Then the FORCE INDEX list 
3652
    (if non-empty) is appended to the USE INDEX list and a flag is set.
3653
3654
    Multiple hints of the same kind are processed so that each clause 
3655
    is applied to what is computed in the previous clause.
3656
    For example:
3657
        USE INDEX (i1) USE INDEX (i2)
3658
    is equivalent to
3659
        USE INDEX (i1,i2)
3660
    and means "consider only i1 and i2".
3661
        
3662
    Similarly
3663
        USE INDEX () USE INDEX (i1)
3664
    is equivalent to
3665
        USE INDEX (i1)
3666
    and means "consider only the index i1"
3667
3668
    It is OK to have the same index several times, e.g. "USE INDEX (i1,i1)" is
3669
    not an error.
3670
        
3671
    Different kind of hints (USE/FORCE/IGNORE) are processed in the following
3672
    order:
3673
      1. All indexes in USE (or FORCE) INDEX are added to the mask.
3674
      2. All IGNORE INDEX
3675
3676
    e.g. "USE INDEX i1, IGNORE INDEX i1, USE INDEX i1" will not use i1 at all
3677
    as if we had "USE INDEX i1, USE INDEX i1, IGNORE INDEX i1".
3678
3679
    As an optimization if there is a covering index, and we have 
3680
    IGNORE INDEX FOR GROUP/ORDER, and this index is used for the JOIN part, 
3681
    then we have to ignore the IGNORE INDEX FROM GROUP/ORDER.
3682
3683
  RETURN VALUE
3684
    FALSE                no errors found
3685
    TRUE                 found and reported an error.
3686
*/
3687
bool TABLE_LIST::process_index_hints(TABLE *tbl)
3688
{
3689
  /* initialize the result variables */
3690
  tbl->keys_in_use_for_query= tbl->keys_in_use_for_group_by= 
3691
    tbl->keys_in_use_for_order_by= tbl->s->keys_in_use;
3692
3693
  /* index hint list processing */
3694
  if (index_hints)
3695
  {
3696
    key_map index_join[INDEX_HINT_FORCE + 1];
3697
    key_map index_order[INDEX_HINT_FORCE + 1];
3698
    key_map index_group[INDEX_HINT_FORCE + 1];
3699
    Index_hint *hint;
3700
    int type;
3701
    bool have_empty_use_join= FALSE, have_empty_use_order= FALSE, 
3702
         have_empty_use_group= FALSE;
3703
    List_iterator <Index_hint> iter(*index_hints);
3704
3705
    /* initialize temporary variables used to collect hints of each kind */
3706
    for (type= INDEX_HINT_IGNORE; type <= INDEX_HINT_FORCE; type++)
3707
    {
3708
      index_join[type].clear_all();
3709
      index_order[type].clear_all();
3710
      index_group[type].clear_all();
3711
    }
3712
3713
    /* iterate over the hints list */
3714
    while ((hint= iter++))
3715
    {
3716
      uint pos;
3717
3718
      /* process empty USE INDEX () */
3719
      if (hint->type == INDEX_HINT_USE && !hint->key_name.str)
3720
      {
3721
        if (hint->clause & INDEX_HINT_MASK_JOIN)
3722
        {
3723
          index_join[hint->type].clear_all();
3724
          have_empty_use_join= TRUE;
3725
        }
3726
        if (hint->clause & INDEX_HINT_MASK_ORDER)
3727
        {
3728
          index_order[hint->type].clear_all();
3729
          have_empty_use_order= TRUE;
3730
        }
3731
        if (hint->clause & INDEX_HINT_MASK_GROUP)
3732
        {
3733
          index_group[hint->type].clear_all();
3734
          have_empty_use_group= TRUE;
3735
        }
3736
        continue;
3737
      }
3738
3739
      /* 
3740
        Check if an index with the given name exists and get his offset in 
3741
        the keys bitmask for the table 
3742
      */
3743
      if (tbl->s->keynames.type_names == 0 ||
3744
          (pos= find_type(&tbl->s->keynames, hint->key_name.str,
3745
                          hint->key_name.length, 1)) <= 0)
3746
      {
3747
        my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), hint->key_name.str, alias);
3748
        return 1;
3749
      }
3750
3751
      pos--;
3752
3753
      /* add to the appropriate clause mask */
3754
      if (hint->clause & INDEX_HINT_MASK_JOIN)
3755
        index_join[hint->type].set_bit (pos);
3756
      if (hint->clause & INDEX_HINT_MASK_ORDER)
3757
        index_order[hint->type].set_bit (pos);
3758
      if (hint->clause & INDEX_HINT_MASK_GROUP)
3759
        index_group[hint->type].set_bit (pos);
3760
    }
3761
3762
    /* cannot mix USE INDEX and FORCE INDEX */
3763
    if ((!index_join[INDEX_HINT_FORCE].is_clear_all() ||
3764
         !index_order[INDEX_HINT_FORCE].is_clear_all() ||
3765
         !index_group[INDEX_HINT_FORCE].is_clear_all()) &&
3766
        (!index_join[INDEX_HINT_USE].is_clear_all() ||  have_empty_use_join ||
3767
         !index_order[INDEX_HINT_USE].is_clear_all() || have_empty_use_order ||
3768
         !index_group[INDEX_HINT_USE].is_clear_all() || have_empty_use_group))
3769
    {
3770
      my_error(ER_WRONG_USAGE, MYF(0), index_hint_type_name[INDEX_HINT_USE],
3771
               index_hint_type_name[INDEX_HINT_FORCE]);
3772
      return 1;
3773
    }
3774
3775
    /* process FORCE INDEX as USE INDEX with a flag */
3776
    if (!index_join[INDEX_HINT_FORCE].is_clear_all() ||
3777
        !index_order[INDEX_HINT_FORCE].is_clear_all() ||
3778
        !index_group[INDEX_HINT_FORCE].is_clear_all())
3779
    {
3780
      tbl->force_index= TRUE;
3781
      index_join[INDEX_HINT_USE].merge(index_join[INDEX_HINT_FORCE]);
3782
      index_order[INDEX_HINT_USE].merge(index_order[INDEX_HINT_FORCE]);
3783
      index_group[INDEX_HINT_USE].merge(index_group[INDEX_HINT_FORCE]);
3784
    }
3785
3786
    /* apply USE INDEX */
3787
    if (!index_join[INDEX_HINT_USE].is_clear_all() || have_empty_use_join)
3788
      tbl->keys_in_use_for_query.intersect(index_join[INDEX_HINT_USE]);
3789
    if (!index_order[INDEX_HINT_USE].is_clear_all() || have_empty_use_order)
3790
      tbl->keys_in_use_for_order_by.intersect (index_order[INDEX_HINT_USE]);
3791
    if (!index_group[INDEX_HINT_USE].is_clear_all() || have_empty_use_group)
3792
      tbl->keys_in_use_for_group_by.intersect (index_group[INDEX_HINT_USE]);
3793
3794
    /* apply IGNORE INDEX */
3795
    tbl->keys_in_use_for_query.subtract (index_join[INDEX_HINT_IGNORE]);
3796
    tbl->keys_in_use_for_order_by.subtract (index_order[INDEX_HINT_IGNORE]);
3797
    tbl->keys_in_use_for_group_by.subtract (index_group[INDEX_HINT_IGNORE]);
3798
  }
3799
3800
  /* make sure covering_keys don't include indexes disabled with a hint */
3801
  tbl->covering_keys.intersect(tbl->keys_in_use_for_query);
3802
  return 0;
3803
}
3804
3805
3806
size_t max_row_length(TABLE *table, const uchar *data)
3807
{
3808
  TABLE_SHARE *table_s= table->s;
3809
  size_t length= table_s->reclength + 2 * table_s->fields;
3810
  uint *const beg= table_s->blob_field;
3811
  uint *const end= beg + table_s->blob_fields;
3812
3813
  for (uint *ptr= beg ; ptr != end ; ++ptr)
3814
  {
3815
    Field_blob* const blob= (Field_blob*) table->field[*ptr];
3816
    length+= blob->get_length((const uchar*)
3817
                              (data + blob->offset(table->record[0]))) +
3818
      HA_KEY_BLOB_LENGTH;
3819
  }
3820
  return length;
3821
}
3822
3823
/*
3824
  Check type of .frm if we are not going to parse it
3825
3826
  SYNOPSIS
3827
  mysql_frm_type()
3828
  path        path to file
3829
3830
  RETURN
3831
  FRMTYPE_ERROR       error                
3832
  FRMTYPE_TABLE       table                
3833
 */    
3834
3835
frm_type_enum mysql_frm_type(THD *thd, char *path, enum legacy_db_type *dbt)
3836
{   
3837
  File file;
3838
  uchar header[10];     /* This should be optimized */
3839
  int error;
3840
  DBUG_ENTER("mysql_frm_type");
3841
3842
  *dbt= DB_TYPE_UNKNOWN;
3843
3844
  if ((file= my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0)
3845
    DBUG_RETURN(FRMTYPE_ERROR);
3846
  error= my_read(file, (uchar*) header, sizeof(header), MYF(MY_NABP));
3847
  my_close(file, MYF(MY_WME));
3848
3849
  if (error)
3850
    DBUG_RETURN(FRMTYPE_ERROR);
3851
3852
  /*  
3853
    This is just a check for DB_TYPE. We'll return default unknown type
3854
    if the following test is true (arg #3). This should not have effect
3855
    on return value from this function (default FRMTYPE_TABLE)
3856
   */  
3857
  if (header[0] != (uchar) 254 || header[1] != 1 ||
3858
      (header[2] != FRM_VER && header[2] != FRM_VER+1 &&
3859
       (header[2] < FRM_VER+3 || header[2] > FRM_VER+4)))
3860
    DBUG_RETURN(FRMTYPE_TABLE);
3861
3862
  *dbt= (enum legacy_db_type) (uint) *(header + 3);
3863
  DBUG_RETURN(FRMTYPE_TABLE);                   // Is probably a .frm table
3864
}
3865
3866
3867
/*****************************************************************************
3868
** Instansiate templates
3869
*****************************************************************************/
3870
3871
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
3872
template class List<String>;
3873
template class List_iterator<String>;
3874
#endif