134
static enum_field_types proto_field_type_to_drizzle_type(uint32_t proto_field_type)
136
enum_field_types field_type;
138
switch(proto_field_type)
140
case message::Table::Field::INTEGER:
141
field_type= DRIZZLE_TYPE_LONG;
143
case message::Table::Field::DOUBLE:
144
field_type= DRIZZLE_TYPE_DOUBLE;
146
case message::Table::Field::TIMESTAMP:
147
field_type= DRIZZLE_TYPE_TIMESTAMP;
149
case message::Table::Field::BIGINT:
150
field_type= DRIZZLE_TYPE_LONGLONG;
152
case message::Table::Field::DATETIME:
153
field_type= DRIZZLE_TYPE_DATETIME;
155
case message::Table::Field::DATE:
156
field_type= DRIZZLE_TYPE_DATE;
158
case message::Table::Field::VARCHAR:
159
field_type= DRIZZLE_TYPE_VARCHAR;
161
case message::Table::Field::DECIMAL:
162
field_type= DRIZZLE_TYPE_DECIMAL;
164
case message::Table::Field::ENUM:
165
field_type= DRIZZLE_TYPE_ENUM;
167
case message::Table::Field::BLOB:
168
field_type= DRIZZLE_TYPE_BLOB;
171
field_type= DRIZZLE_TYPE_LONG; /* Set value to kill GCC warning */
182
Initialize share for temporary tables
185
init_tmp_table_share()
186
session thread handle
188
key Table_cache_key, as generated from create_table_def_key.
189
must start with db name.
190
key_length Length of key
191
table_name Table name
192
path Path to file (possible in lower case) without .frm
195
This is different from alloc_table_share() because temporary tables
196
don't have to be shared between threads or put into the table def
197
cache, so we can do some things notable simpler and faster
199
If table is not put in session->temporary_tables (happens only when
200
one uses OPEN TEMPORARY) then one can specify 'db' as key and
201
use key_length= 0 as neither table_cache_key or key_length will be used).
204
void init_tmp_table_share(Session *session, TABLE_SHARE *share, const char *key,
205
uint32_t key_length, const char *table_name,
209
memset(share, 0, sizeof(*share));
210
init_sql_alloc(&share->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
211
share->table_category= TABLE_CATEGORY_TEMPORARY;
212
share->tmp_table= INTERNAL_TMP_TABLE;
213
share->db.str= (char*) key;
214
share->db.length= strlen(key);
215
share->table_cache_key.str= (char*) key;
216
share->table_cache_key.length= key_length;
217
share->table_name.str= (char*) table_name;
218
share->table_name.length= strlen(table_name);
219
share->path.str= (char*) path;
220
share->normalized_path.str= (char*) path;
221
share->path.length= share->normalized_path.length= strlen(path);
224
Temporary tables are not replicated, but we set up these fields
225
anyway to be able to catch errors.
227
share->table_map_version= ~(uint64_t)0;
228
share->cached_row_logging_check= -1;
231
table_map_id is also used for MERGE tables to suppress repeated
232
compatibility checks.
234
share->table_map_id= (ulong) session->query_id;
241
Free table share and memory used by it
248
share->mutex must be locked when we come here if it's not a temp table
251
void free_table_share(TABLE_SHARE *share)
254
assert(share->ref_count == 0);
257
If someone is waiting for this to be deleted, inform it about this.
258
Don't do a delete until we know that no one is refering to this anymore.
260
if (share->tmp_table == NO_TMP_TABLE)
262
/* share->mutex is locked in release_table_share() */
263
while (share->waiting_on_cond)
265
pthread_cond_broadcast(&share->cond);
266
pthread_cond_wait(&share->cond, &share->mutex);
268
/* No thread refers to this anymore */
269
pthread_mutex_unlock(&share->mutex);
270
pthread_mutex_destroy(&share->mutex);
271
pthread_cond_destroy(&share->cond);
273
hash_free(&share->name_hash);
275
plugin_unlock(NULL, share->db_plugin);
276
share->db_plugin= NULL;
278
/* We must copy mem_root from share because share is allocated through it */
279
memcpy(&mem_root, &share->mem_root, sizeof(mem_root));
280
free_root(&mem_root, MYF(0)); // Free's share
285
Read table definition from a binary / text based .frm file
289
session Thread handler
290
share Fill this with table definition
291
db_flags Bit mask of the following flags: OPEN_VIEW
294
This function is called when the table definition is not cached in
296
The data is returned in 'share', which is alloced by
297
alloc_table_share().. The code assumes that share is initialized.
301
1 Error (see open_table_error)
302
2 Error (see open_table_error)
303
3 Wrong data in .frm file
304
4 Error (see open_table_error)
305
5 Error (see open_table_error: charset unavailable)
306
6 Unknown .frm version
309
int open_table_def(Session *session, TABLE_SHARE *share, uint32_t)
311
int error, table_type;
314
unsigned char head[64], *disk_buff;
317
MEM_ROOT **root_ptr, *old_root;
323
path.reserve(FN_REFLEN);
324
path.append(share->normalized_path.str);
325
path.append(reg_ext);
326
if ((file= open(path.c_str(), O_RDONLY)) < 0)
329
We don't try to open 5.0 unencoded name, if
330
- non-encoded name contains '@' signs,
331
because '@' can be misinterpreted.
332
It is not clear if '@' is escape character in 5.1,
333
or a normal character in 5.0.
335
- non-encoded db or table name contain "#mysql50#" prefix.
336
This kind of tables must have been opened only by the
339
if (strchr(share->table_name.str, '@') ||
340
!strncmp(share->db.str, MYSQL50_TABLE_NAME_PREFIX,
341
MYSQL50_TABLE_NAME_PREFIX_LENGTH) ||
342
!strncmp(share->table_name.str, MYSQL50_TABLE_NAME_PREFIX,
343
MYSQL50_TABLE_NAME_PREFIX_LENGTH))
346
/* Try unencoded 5.0 name */
348
char unpacked_path[FN_REFLEN];
350
path.append(drizzle_data_home);
352
path.append(share->db.str);
354
path.append(share->table_name.str);
355
path.append(reg_ext);
356
length= unpack_filename(unpacked_path, path.c_str()) - reg_ext_length;
358
The following is a safety test and should never fail
359
as the old file name should never be longer than the new one.
361
assert(length <= share->normalized_path.length);
363
If the old and the new names have the same length,
364
then table name does not have tricky characters,
365
so no need to check the old file name.
367
if (length == share->normalized_path.length ||
368
((file= open(unpacked_path, O_RDONLY)) < 0))
371
/* Unencoded 5.0 table name found */
372
unpacked_path[length]= '\0'; // Remove .frm extension
373
strcpy(share->normalized_path.str, unpacked_path);
374
share->normalized_path.length= length;
378
if (my_read(file, head, 64, MYF(MY_NABP)))
381
if (head[0] == (unsigned char) 254 && head[1] == 1)
383
if (head[2] == FRM_VER || head[2] == FRM_VER+1 ||
384
(head[2] >= FRM_VER+3 && head[2] <= FRM_VER+4))
390
error= 6; // Unkown .frm version
397
/* No handling of text based files yet */
400
root_ptr= current_mem_root_ptr();
402
*root_ptr= &share->mem_root;
403
error= open_binary_frm(session, share, head, file);
178
static Item *default_value_item(enum_field_types field_type,
179
const CHARSET_INFO *charset,
180
bool default_null, const string *default_value,
181
const string *default_bin_value)
183
Item *default_item= NULL;
188
return new Item_null();
193
case DRIZZLE_TYPE_LONG:
194
case DRIZZLE_TYPE_LONGLONG:
195
default_item= new Item_int(default_value->c_str(),
196
(int64_t) internal::my_strtoll10(default_value->c_str(),
199
default_value->length());
201
case DRIZZLE_TYPE_DOUBLE:
202
default_item= new Item_float(default_value->c_str(),
203
default_value->length());
205
case DRIZZLE_TYPE_NULL:
207
case DRIZZLE_TYPE_TIMESTAMP:
208
case DRIZZLE_TYPE_DATETIME:
209
case DRIZZLE_TYPE_DATE:
210
if (default_value->compare("NOW()") == 0)
212
case DRIZZLE_TYPE_ENUM:
213
default_item= new Item_string(default_value->c_str(),
214
default_value->length(),
215
system_charset_info);
217
case DRIZZLE_TYPE_VARCHAR:
218
case DRIZZLE_TYPE_BLOB: /* Blob is here due to TINYTEXT. Feel the hate. */
219
if (charset==&my_charset_bin)
221
default_item= new Item_string(default_bin_value->c_str(),
222
default_bin_value->length(),
227
default_item= new Item_string(default_value->c_str(),
228
default_value->length(),
229
system_charset_info);
232
case DRIZZLE_TYPE_DECIMAL:
233
default_item= new Item_decimal(default_value->c_str(),
234
default_value->length(),
235
system_charset_info);
242
int parse_table_proto(Session& session,
243
message::Table &table,
248
if (! table.IsInitialized())
250
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), table.InitializationErrorString().c_str());
251
return ER_CORRUPT_TABLE_DEFINITION;
254
share->setTableProto(new(nothrow) message::Table(table));
256
share->storage_engine= plugin::StorageEngine::findByName(session, table.engine().name());
257
assert(share->storage_engine); // We use an assert() here because we should never get this far and still have no suitable engine.
259
message::Table::TableOptions table_options;
261
if (table.has_options())
262
table_options= table.options();
264
uint32_t db_create_options= 0;
266
if (table_options.has_pack_keys())
268
if (table_options.pack_keys())
269
db_create_options|= HA_OPTION_PACK_KEYS;
271
db_create_options|= HA_OPTION_NO_PACK_KEYS;
274
if (table_options.pack_record())
275
db_create_options|= HA_OPTION_PACK_RECORD;
277
/* db_create_options was stored as 2 bytes in FRM
278
Any HA_OPTION_ that doesn't fit into 2 bytes was silently truncated away.
280
share->db_create_options= (db_create_options & 0x0000FFFF);
410
share->table_category= get_table_category(& share->db, & share->table_name);
413
session->status_var.opened_shares++;
416
my_close(file, MYF(MY_WME));
419
if (error && !error_given)
422
open_table_error(share, error, (share->open_errno= my_errno), 0);
430
Read data from a binary .frm file from MySQL 3.23 - 5.0 into TABLE_SHARE
433
static int open_binary_frm(Session *session, TABLE_SHARE *share, unsigned char *head,
436
int error, errarg= 0;
437
uint32_t new_frm_ver, field_pack_length, new_field_pack_flag;
438
uint32_t interval_count, interval_parts, read_length, int_length;
439
uint32_t db_create_options, keys, key_parts, n_length;
440
uint32_t key_info_length, com_length, null_bit_pos=0;
441
uint32_t vcol_screen_length;
442
uint32_t extra_rec_buf_length;
445
unsigned char forminfo[288];
446
char *keynames, *names, *comment_pos, *vcol_screen_pos;
447
unsigned char *record;
448
unsigned char *disk_buff, *strpos, *null_flags=NULL, *null_pos=NULL;
449
ulong pos, record_offset, *rec_per_key, rec_buff_length;
450
handler *handler_file= 0;
452
KEY_PART_INFO *key_part;
453
Field **field_ptr, *reg_field;
454
const char **interval_array;
455
enum legacy_db_type legacy_db_type;
456
my_bitmap_map *bitmaps;
457
unsigned char *buff= 0;
458
unsigned char *field_extra_info= 0;
460
new_field_pack_flag= head[27];
461
new_frm_ver= (head[2] - FRM_VER);
462
field_pack_length= new_frm_ver < 2 ? 11 : 17;
466
if (!(pos=get_form_pos(file,head,(TYPELIB*) 0)))
467
goto err; /* purecov: inspected */
468
lseek(file,pos,SEEK_SET);
469
if (my_read(file,forminfo,288,MYF(MY_NABP)))
472
legacy_db_type= DB_TYPE_FIRST_DYNAMIC;
473
assert(share->db_plugin == NULL);
475
if the storage engine is dynamic, no point in resolving it by its
476
dynamically allocated legacy_db_type. We will resolve it later by name.
478
if (legacy_db_type > DB_TYPE_UNKNOWN &&
479
legacy_db_type < DB_TYPE_FIRST_DYNAMIC)
480
share->db_plugin= ha_lock_engine(NULL,
481
ha_checktype(session, legacy_db_type, 0, 0));
482
share->db_create_options= db_create_options= uint2korr(head+30);
281
483
share->db_options_in_use= share->db_create_options;
283
share->row_type= table_options.has_row_type() ?
284
(enum row_type) table_options.row_type() : ROW_TYPE_DEFAULT;
286
share->block_size= table_options.has_block_size() ?
287
table_options.block_size() : 0;
289
share->table_charset= get_charset(table_options.has_collation_id()?
290
table_options.collation_id() : 0);
484
share->mysql_version= uint4korr(head+51);
485
share->null_field_first= 0;
486
if (!head[32]) // New frm file in 3.23
488
share->avg_row_length= uint4korr(head+34);
489
share->transactional= (ha_choice) (head[39] & 3);
490
share->page_checksum= (ha_choice) ((head[39] >> 2) & 3);
491
share->row_type= (row_type) head[40];
492
share->block_size= uint4korr(head+43);
493
share->table_charset= get_charset((uint) head[38],MYF(0));
494
share->null_field_first= 1;
292
496
if (!share->table_charset)
294
498
/* unknown charset in head[38] or pre-3.23 frm */
295
499
if (use_mb(default_charset_info))
297
501
/* Warn that we may be changing the size of character columns */
298
errmsg_printf(ERRMSG_LVL_WARN,
299
_("'%s' had no or invalid character set, "
300
"and default character set is multi-byte, "
301
"so character column sizes may have changed"),
502
errmsg_printf(ERRMSG_LVL_WARN, _("'%s' had no or invalid character set, "
503
"and default character set is multi-byte, "
504
"so character column sizes may have changed"),
304
507
share->table_charset= default_charset_info;
307
509
share->db_record_offset= 1;
309
share->blob_ptr_size= portable_sizeof_char_ptr; // more bonghits.
311
share->keys= table.indexes_size();
314
for (int indx= 0; indx < table.indexes_size(); indx++)
315
share->key_parts+= table.indexes(indx).index_part_size();
317
share->key_info= (KEY*) alloc_root(&share->mem_root,
318
table.indexes_size() * sizeof(KEY)
319
+share->key_parts*sizeof(KEY_PART_INFO));
321
KEY_PART_INFO *key_part;
323
key_part= reinterpret_cast<KEY_PART_INFO*>
324
(share->key_info+table.indexes_size());
327
ulong *rec_per_key= (ulong*) alloc_root(&share->mem_root,
328
sizeof(ulong*)*share->key_parts);
330
share->keynames.count= table.indexes_size();
331
share->keynames.name= NULL;
332
share->keynames.type_names= (const char**)
333
alloc_root(&share->mem_root, sizeof(char*) * (table.indexes_size()+1));
335
share->keynames.type_lengths= (unsigned int*)
336
alloc_root(&share->mem_root,
337
sizeof(unsigned int) * (table.indexes_size()+1));
339
share->keynames.type_names[share->keynames.count]= NULL;
340
share->keynames.type_lengths[share->keynames.count]= 0;
342
KEY* keyinfo= share->key_info;
343
for (int keynr= 0; keynr < table.indexes_size(); keynr++, keyinfo++)
345
message::Table::Index indx= table.indexes(keynr);
350
if (indx.is_unique())
351
keyinfo->flags|= HA_NOSAME;
353
if (indx.has_options())
355
message::Table::Index::IndexOptions indx_options= indx.options();
356
if (indx_options.pack_key())
357
keyinfo->flags|= HA_PACK_KEY;
359
if (indx_options.var_length_key())
360
keyinfo->flags|= HA_VAR_LENGTH_PART;
362
if (indx_options.null_part_key())
363
keyinfo->flags|= HA_NULL_PART_KEY;
365
if (indx_options.binary_pack_key())
366
keyinfo->flags|= HA_BINARY_PACK_KEY;
368
if (indx_options.has_partial_segments())
369
keyinfo->flags|= HA_KEY_HAS_PART_KEY_SEG;
371
if (indx_options.auto_generated_key())
372
keyinfo->flags|= HA_GENERATED_KEY;
374
if (indx_options.has_key_block_size())
376
keyinfo->flags|= HA_USES_BLOCK_SIZE;
377
keyinfo->block_size= indx_options.key_block_size();
381
keyinfo->block_size= 0;
387
case message::Table::Index::UNKNOWN_INDEX:
388
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
390
case message::Table::Index::BTREE:
391
keyinfo->algorithm= HA_KEY_ALG_BTREE;
393
case message::Table::Index::HASH:
394
keyinfo->algorithm= HA_KEY_ALG_HASH;
398
/* TODO: suitable warning ? */
399
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
403
keyinfo->key_length= indx.key_length();
405
keyinfo->key_parts= indx.index_part_size();
407
keyinfo->key_part= key_part;
510
if (db_create_options & HA_OPTION_LONG_BLOB_PTR)
511
share->blob_ptr_size= portable_sizeof_char_ptr;
512
/* Set temporarily a good value for db_low_byte_first */
513
share->db_low_byte_first= true;
515
share->max_rows= uint4korr(head+18);
516
share->min_rows= uint4korr(head+22);
518
/* Read keyinformation */
519
key_info_length= (uint) uint2korr(head+28);
520
lseek(file,(ulong) uint2korr(head+6),SEEK_SET);
521
if (read_string(file,(unsigned char**) &disk_buff,key_info_length))
522
goto err; /* purecov: inspected */
523
if (disk_buff[0] & 0x80)
525
share->keys= keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
526
share->key_parts= key_parts= uint2korr(disk_buff+2);
530
share->keys= keys= disk_buff[0];
531
share->key_parts= key_parts= disk_buff[1];
533
share->keys_for_keyread.init(0);
534
share->keys_in_use.init(keys);
536
n_length=keys*sizeof(KEY)+key_parts*sizeof(KEY_PART_INFO);
537
if (!(keyinfo = (KEY*) alloc_root(&share->mem_root,
538
n_length + uint2korr(disk_buff+4))))
539
goto err; /* purecov: inspected */
540
memset(keyinfo, 0, n_length);
541
share->key_info= keyinfo;
542
key_part= reinterpret_cast<KEY_PART_INFO*> (keyinfo+keys);
545
if (!(rec_per_key= (ulong*) alloc_root(&share->mem_root,
546
sizeof(ulong*)*key_parts)))
549
for (i=0 ; i < keys ; i++, keyinfo++)
551
keyinfo->table= 0; // Updated in open_frm
552
if (new_frm_ver >= 3)
554
keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
555
keyinfo->key_length= (uint) uint2korr(strpos+2);
556
keyinfo->key_parts= (uint) strpos[4];
557
keyinfo->algorithm= (enum ha_key_alg) strpos[5];
558
keyinfo->block_size= uint2korr(strpos+6);
562
keyinfo->key_part= key_part;
408
563
keyinfo->rec_per_key= rec_per_key;
410
for (unsigned int partnr= 0;
411
partnr < keyinfo->key_parts;
412
partnr++, key_part++)
414
message::Table::Index::IndexPart part;
415
part= indx.index_part(partnr);
419
key_part->field= NULL;
420
key_part->fieldnr= part.fieldnr() + 1; // start from 1.
421
key_part->null_bit= 0;
422
/* key_part->null_offset is only set if null_bit (see later) */
423
/* key_part->key_type= */ /* I *THINK* this may be okay.... */
424
/* key_part->type ???? */
425
key_part->key_part_flag= 0;
426
if (part.has_in_reverse_order())
427
key_part->key_part_flag= part.in_reverse_order()? HA_REVERSE_SORT : 0;
429
key_part->length= part.compare_length();
431
key_part->store_length= key_part->length;
433
/* key_part->offset is set later */
434
key_part->key_type= part.key_type();
437
if (! indx.has_comment())
439
keyinfo->comment.length= 0;
440
keyinfo->comment.str= NULL;
444
keyinfo->flags|= HA_USES_COMMENT;
445
keyinfo->comment.length= indx.comment().length();
446
keyinfo->comment.str= strmake_root(&share->mem_root,
447
indx.comment().c_str(),
448
keyinfo->comment.length);
451
keyinfo->name= strmake_root(&share->mem_root,
453
indx.name().length());
455
share->keynames.type_names[keynr]= keyinfo->name;
456
share->keynames.type_lengths[keynr]= indx.name().length();
459
share->keys_for_keyread.reset();
460
set_prefix(share->keys_in_use, share->keys);
462
share->fields= table.field_size();
464
share->field= (Field**) alloc_root(&share->mem_root,
465
((share->fields+1) * sizeof(Field*)));
466
share->field[share->fields]= NULL;
468
uint32_t null_fields= 0;
471
uint32_t *field_offsets= (uint32_t*)malloc(share->fields * sizeof(uint32_t));
472
uint32_t *field_pack_length=(uint32_t*)malloc(share->fields*sizeof(uint32_t));
474
assert(field_offsets && field_pack_length); // TODO: fixme
476
uint32_t interval_count= 0;
477
uint32_t interval_parts= 0;
479
uint32_t stored_columns_reclength= 0;
481
for (unsigned int fieldnr= 0; fieldnr < share->fields; fieldnr++)
483
message::Table::Field pfield= table.field(fieldnr);
484
if (pfield.constraints().is_nullable())
487
enum_field_types drizzle_field_type=
488
proto_field_type_to_drizzle_type(pfield.type());
490
field_offsets[fieldnr]= stored_columns_reclength;
492
/* the below switch is very similar to
493
CreateField::create_length_to_internal_length in field.cc
494
(which should one day be replace by just this code)
496
switch(drizzle_field_type)
498
case DRIZZLE_TYPE_BLOB:
499
case DRIZZLE_TYPE_VARCHAR:
501
message::Table::Field::StringFieldOptions field_options= pfield.string_options();
503
const CHARSET_INFO *cs= get_charset(field_options.has_collation_id() ?
504
field_options.collation_id() : 0);
507
cs= default_charset_info;
509
field_pack_length[fieldnr]= calc_pack_length(drizzle_field_type,
510
field_options.length() * cs->mbmaxlen);
513
case DRIZZLE_TYPE_ENUM:
515
message::Table::Field::EnumerationValues field_options= pfield.enumeration_values();
517
field_pack_length[fieldnr]=
518
get_enum_pack_length(field_options.field_value_size());
521
interval_parts+= field_options.field_value_size();
524
case DRIZZLE_TYPE_DECIMAL:
526
message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
528
field_pack_length[fieldnr]= my_decimal_get_binary_size(fo.precision(), fo.scale());
532
/* Zero is okay here as length is fixed for other types. */
533
field_pack_length[fieldnr]= calc_pack_length(drizzle_field_type, 0);
536
share->reclength+= field_pack_length[fieldnr];
537
stored_columns_reclength+= field_pack_length[fieldnr];
540
/* data_offset added to stored_rec_length later */
541
share->stored_rec_length= stored_columns_reclength;
543
share->null_fields= null_fields;
545
ulong null_bits= null_fields;
546
if (! table_options.pack_record())
548
ulong data_offset= (null_bits + 7)/8;
551
share->reclength+= data_offset;
552
share->stored_rec_length+= data_offset;
554
ulong rec_buff_length;
556
rec_buff_length= ALIGN_SIZE(share->reclength + 1);
564
for (j=keyinfo->key_parts ; j-- ; key_part++)
567
key_part->fieldnr= (uint16_t) (uint2korr(strpos) & FIELD_NR_MASK);
568
key_part->offset= (uint) uint2korr(strpos+2)-1;
569
key_part->key_type= (uint) uint2korr(strpos+5);
570
// key_part->field= (Field*) 0; // Will be fixed later
571
if (new_frm_ver >= 1)
573
key_part->key_part_flag= *(strpos+4);
574
key_part->length= (uint) uint2korr(strpos+7);
579
key_part->length= *(strpos+4);
580
key_part->key_part_flag=0;
581
if (key_part->length > 128)
583
key_part->length&=127; /* purecov: inspected */
584
key_part->key_part_flag=HA_REVERSE_SORT; /* purecov: inspected */
588
key_part->store_length=key_part->length;
591
keynames=(char*) key_part;
592
strpos+= (strcpy(keynames, (char*)strpos)+strlen((char*)strpos)-keynames)+1;
594
//reading index comments
595
for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++)
597
if (keyinfo->flags & HA_USES_COMMENT)
599
keyinfo->comment.length= uint2korr(strpos);
600
keyinfo->comment.str= strmake_root(&share->mem_root, (char*) strpos+2,
601
keyinfo->comment.length);
602
strpos+= 2 + keyinfo->comment.length;
604
assert(test(keyinfo->flags & HA_USES_COMMENT) ==
605
(keyinfo->comment.length > 0));
608
share->reclength = uint2korr((head+16));
609
share->stored_rec_length= share->reclength;
611
record_offset= (ulong) (uint2korr(head+6)+
612
((uint2korr(head+14) == 0xffff ?
613
uint4korr(head+47) : uint2korr(head+14))));
615
if ((n_length= uint4korr(head+55)))
617
/* Read extra data segment */
618
unsigned char *next_chunk, *buff_end;
619
if (!(next_chunk= buff= (unsigned char*) malloc(n_length)))
621
if (pread(file, buff, n_length, record_offset + share->reclength) == 0)
625
share->connect_string.length= uint2korr(buff);
626
if (!(share->connect_string.str= strmake_root(&share->mem_root,
627
(char*) next_chunk + 2,
628
share->connect_string.
633
next_chunk+= share->connect_string.length + 2;
634
buff_end= buff + n_length;
635
if (next_chunk + 2 < buff_end)
637
uint32_t str_db_type_length= uint2korr(next_chunk);
639
name.str= (char*) next_chunk + 2;
640
name.length= str_db_type_length;
642
plugin_ref tmp_plugin= ha_resolve_by_name(session, &name);
643
if (tmp_plugin != NULL && !plugin_equals(tmp_plugin, share->db_plugin))
645
if (legacy_db_type > DB_TYPE_UNKNOWN &&
646
legacy_db_type < DB_TYPE_FIRST_DYNAMIC &&
647
legacy_db_type != ha_legacy_type(
648
plugin_data(tmp_plugin, handlerton *)))
650
/* bad file, legacy_db_type did not match the name */
655
tmp_plugin is locked with a local lock.
656
we unlock the old value of share->db_plugin before
657
replacing it with a globally locked version of tmp_plugin
659
plugin_unlock(NULL, share->db_plugin);
660
share->db_plugin= my_plugin_lock(NULL, &tmp_plugin);
662
else if (!tmp_plugin)
664
/* purecov: begin inspected */
666
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str);
671
next_chunk+= str_db_type_length + 2;
673
if (share->mysql_version >= 50110)
675
/* New auto_partitioned indicator introduced in 5.1.11 */
678
if (forminfo[46] == (unsigned char)255)
680
//reading long table comment
681
if (next_chunk + 2 > buff_end)
686
share->comment.length = uint2korr(next_chunk);
687
if (! (share->comment.str= strmake_root(&share->mem_root,
688
(char*)next_chunk + 2, share->comment.length)))
693
next_chunk+= 2 + share->comment.length;
695
assert(next_chunk <= buff_end);
696
if (share->mysql_version >= DRIZZLE_VERSION_TABLESPACE_IN_FRM_CGE)
699
New frm format in mysql_version 5.2.5 (originally in
700
mysql-5.1.22-ndb-6.2.5)
701
New column properties added:
702
COLUMN_FORMAT DYNAMIC|FIXED and STORAGE DISK|MEMORY
703
TABLESPACE name is now stored in frm
705
if (next_chunk >= buff_end)
707
if (share->mysql_version >= DRIZZLE_VERSION_TABLESPACE_IN_FRM)
714
const uint32_t format_section_header_size= 8;
715
uint32_t format_section_len= uint2korr(next_chunk+0);
717
field_extra_info= next_chunk + format_section_header_size + 1;
718
next_chunk+= format_section_len;
721
assert (next_chunk <= buff_end);
722
if (next_chunk > buff_end)
727
share->key_block_size= uint2korr(head+62);
730
extra_rec_buf_length= uint2korr(head+59);
731
rec_buff_length= ALIGN_SIZE(share->reclength + 1 + extra_rec_buf_length);
557
732
share->rec_buff_length= rec_buff_length;
559
unsigned char* record= NULL;
561
if (! (record= (unsigned char *) alloc_root(&share->mem_root,
565
memset(record, 0, rec_buff_length);
569
if (! table_options.pack_record())
571
null_count++; // one bit for delete mark.
733
if (!(record= (unsigned char *) alloc_root(&share->mem_root,
735
goto err; /* purecov: inspected */
575
736
share->default_values= record;
737
if (pread(file, record, (size_t) share->reclength, record_offset) == 0)
738
goto err; /* purecov: inspected */
740
lseek(file,pos+288,SEEK_SET);
742
share->fields= uint2korr(forminfo+258);
743
pos= uint2korr(forminfo+260); /* Length of all screens */
744
n_length= uint2korr(forminfo+268);
745
interval_count= uint2korr(forminfo+270);
746
interval_parts= uint2korr(forminfo+272);
747
int_length= uint2korr(forminfo+274);
748
share->null_fields= uint2korr(forminfo+282);
749
com_length= uint2korr(forminfo+284);
750
vcol_screen_length= uint2korr(forminfo+286);
752
share->stored_fields= share->fields;
753
if (forminfo[46] != (unsigned char)255)
579
share->intervals= (TYPELIB *) alloc_root(&share->mem_root,
580
interval_count*sizeof(TYPELIB));
755
share->comment.length= (int) (forminfo[46]);
756
share->comment.str= strmake_root(&share->mem_root, (char*) forminfo+47,
757
share->comment.length);
583
share->intervals= NULL;
585
share->fieldnames.type_names= (const char **) alloc_root(&share->mem_root,
586
(share->fields + 1) * sizeof(char*));
588
share->fieldnames.type_lengths= (unsigned int *) alloc_root(&share->mem_root,
589
(share->fields + 1) * sizeof(unsigned int));
591
share->fieldnames.type_names[share->fields]= NULL;
592
share->fieldnames.type_lengths[share->fields]= 0;
593
share->fieldnames.count= share->fields;
596
/* Now fix the TYPELIBs for the intervals (enum values)
600
uint32_t interval_nr= 0;
602
for (unsigned int fieldnr= 0; fieldnr < share->fields; fieldnr++)
761
if (!(field_ptr = (Field **)
762
alloc_root(&share->mem_root,
763
(uint) ((share->fields+1)*sizeof(Field*)+
764
interval_count*sizeof(TYPELIB)+
765
(share->fields+interval_parts+
766
keys+3)*sizeof(char *)+
767
(n_length+int_length+
768
vcol_screen_length)))))
769
goto err; /* purecov: inspected */
771
share->field= field_ptr;
772
read_length=(uint) (share->fields * field_pack_length +
773
pos+ (uint) (n_length+int_length+com_length+
774
vcol_screen_length));
775
if (read_string(file,(unsigned char**) &disk_buff,read_length))
776
goto err; /* purecov: inspected */
777
strpos= disk_buff+pos;
779
share->intervals= (TYPELIB*) (field_ptr+share->fields+1);
780
interval_array= (const char **) (share->intervals+interval_count);
781
names= (char*) (interval_array+share->fields+interval_parts+keys+3);
783
share->intervals= 0; // For better debugging
784
memcpy(names, strpos+(share->fields*field_pack_length),
785
(uint) (n_length+int_length));
786
comment_pos= (char *)(disk_buff+read_length-com_length-vcol_screen_length);
787
vcol_screen_pos= names+(n_length+int_length);
788
memcpy(vcol_screen_pos, disk_buff+read_length-vcol_screen_length,
791
fix_type_pointers(&interval_array, &share->fieldnames, 1, &names);
792
if (share->fieldnames.count != share->fields)
794
fix_type_pointers(&interval_array, share->intervals, interval_count,
604
message::Table::Field pfield= table.field(fieldnr);
607
share->fieldnames.type_names[fieldnr]= strmake_root(&share->mem_root,
608
pfield.name().c_str(),
609
pfield.name().length());
611
share->fieldnames.type_lengths[fieldnr]= pfield.name().length();
614
if (pfield.type() != message::Table::Field::ENUM)
617
message::Table::Field::EnumerationValues field_options= pfield.enumeration_values();
619
const CHARSET_INFO *charset= get_charset(field_options.has_collation_id() ?
620
field_options.collation_id() : 0);
623
charset= default_charset_info;
625
TYPELIB *t= &(share->intervals[interval_nr]);
627
t->type_names= (const char**)alloc_root(&share->mem_root,
628
(field_options.field_value_size() + 1) * sizeof(char*));
630
t->type_lengths= (unsigned int*) alloc_root(&share->mem_root,
631
(field_options.field_value_size() + 1) * sizeof(unsigned int));
633
t->type_names[field_options.field_value_size()]= NULL;
634
t->type_lengths[field_options.field_value_size()]= 0;
636
t->count= field_options.field_value_size();
639
for (int n= 0; n < field_options.field_value_size(); n++)
798
/* Set ENUM and SET lengths */
800
for (interval= share->intervals;
801
interval < share->intervals + interval_count;
641
t->type_names[n]= strmake_root(&share->mem_root,
642
field_options.field_value(n).c_str(),
643
field_options.field_value(n).length());
646
* Go ask the charset what the length is as for "" length=1
647
* and there's stripping spaces or some other crack going on.
650
lengthsp= charset->cset->lengthsp(charset,
652
field_options.field_value(n).length());
653
t->type_lengths[n]= lengthsp;
804
uint32_t count= (uint) (interval->count + 1) * sizeof(uint);
805
if (!(interval->type_lengths= (uint32_t *) alloc_root(&share->mem_root,
808
for (count= 0; count < interval->count; count++)
810
char *val= (char*) interval->type_names[count];
811
interval->type_lengths[count]= strlen(val);
813
interval->type_lengths[count]= 0;
659
/* and read the fields */
662
bool use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
818
fix_type_pointers(&interval_array, &share->keynames, 1, &keynames);
820
/* Allocate handler */
821
if (!(handler_file= get_new_handler(share, session->mem_root,
825
record= share->default_values-1; /* Fieldstart = 1 */
826
if (share->null_field_first)
828
null_flags= null_pos= (unsigned char*) record+1;
829
null_bit_pos= (db_create_options & HA_OPTION_PACK_RECORD) ? 0 : 1;
831
null_bytes below is only correct under the condition that
832
there are no bit fields. Correct values is set below after the
833
table struct is initialized
835
share->null_bytes= (share->null_fields + null_bit_pos + 7) / 8;
838
use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
665
use_hash= ! hash_init(&share->name_hash,
670
(hash_get_key) get_field_name,
674
unsigned char* null_pos= record;;
675
int null_bit_pos= (table_options.pack_record()) ? 0 : 1;
677
for (unsigned int fieldnr= 0; fieldnr < share->fields; fieldnr++)
840
use_hash= !hash_init(&share->name_hash,
843
(hash_get_key) get_field_name,0,0);
845
for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
679
message::Table::Field pfield= table.field(fieldnr);
847
uint32_t pack_flag, interval_nr, unireg_type, recpos, field_length;
848
uint32_t vcol_info_length=0;
849
enum_field_types field_type;
681
850
enum column_format_type column_format= COLUMN_FORMAT_TYPE_DEFAULT;
683
switch (pfield.format())
685
case message::Table::Field::DefaultFormat:
686
column_format= COLUMN_FORMAT_TYPE_DEFAULT;
688
case message::Table::Field::FixedFormat:
689
column_format= COLUMN_FORMAT_TYPE_FIXED;
691
case message::Table::Field::DynamicFormat:
692
column_format= COLUMN_FORMAT_TYPE_DYNAMIC;
698
Field::utype unireg_type= Field::NONE;
700
if (pfield.has_numeric_options() &&
701
pfield.numeric_options().is_autoincrement())
703
unireg_type= Field::NEXT_NUMBER;
706
if (pfield.has_options() &&
707
pfield.options().has_default_value() &&
708
pfield.options().default_value().compare("NOW()") == 0)
710
if (pfield.options().has_update_value() &&
711
pfield.options().update_value().compare("NOW()") == 0)
713
unireg_type= Field::TIMESTAMP_DNUN_FIELD;
715
else if (! pfield.options().has_update_value())
717
unireg_type= Field::TIMESTAMP_DN_FIELD;
720
assert(1); // Invalid update value.
722
else if (pfield.has_options() &&
723
pfield.options().has_update_value() &&
724
pfield.options().update_value().compare("NOW()") == 0)
726
unireg_type= Field::TIMESTAMP_UN_FIELD;
851
const CHARSET_INFO *charset= NULL;
729
852
LEX_STRING comment;
730
if (!pfield.has_comment())
732
comment.str= (char*)"";
737
size_t len= pfield.comment().length();
738
const char* str= pfield.comment().c_str();
740
comment.str= strmake_root(&share->mem_root, str, len);
744
enum_field_types field_type;
746
field_type= proto_field_type_to_drizzle_type(pfield.type());
748
const CHARSET_INFO *charset= &my_charset_bin;
750
if (field_type == DRIZZLE_TYPE_BLOB ||
751
field_type == DRIZZLE_TYPE_VARCHAR)
753
message::Table::Field::StringFieldOptions field_options= pfield.string_options();
755
charset= get_charset(field_options.has_collation_id() ?
756
field_options.collation_id() : 0);
759
charset= default_charset_info;
762
if (field_type == DRIZZLE_TYPE_ENUM)
764
message::Table::Field::EnumerationValues field_options= pfield.enumeration_values();
766
charset= get_charset(field_options.has_collation_id()?
767
field_options.collation_id() : 0);
770
charset= default_charset_info;
774
if (field_type == DRIZZLE_TYPE_DECIMAL
775
|| field_type == DRIZZLE_TYPE_DOUBLE)
777
message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
779
if (! pfield.has_numeric_options() || ! fo.has_scale())
853
virtual_column_info *vcol_info= NULL;
854
bool fld_is_stored= true;
856
if (field_extra_info)
858
char tmp= field_extra_info[i];
859
column_format= (enum column_format_type)
860
((tmp >> COLUMN_FORMAT_SHIFT) & COLUMN_FORMAT_MASK);
862
if (new_frm_ver >= 3)
864
/* new frm file in 4.1 */
865
field_length= uint2korr(strpos+3);
866
recpos= uint3korr(strpos+5);
867
pack_flag= uint2korr(strpos+8);
868
unireg_type= (uint) strpos[10];
869
interval_nr= (uint) strpos[12];
870
uint32_t comment_length=uint2korr(strpos+15);
871
field_type=(enum_field_types) (uint) strpos[13];
875
charset= &my_charset_bin;
876
else if (!(charset=get_charset((uint) strpos[14], MYF(0))))
878
error= 5; // Unknown or unavailable charset
879
errarg= (int) strpos[14];
883
if (field_type == DRIZZLE_TYPE_VIRTUAL)
885
assert(interval_nr); // Expect non-null expression
782
We don't write the default to table proto so
783
if no decimals specified for DOUBLE, we use the default.
887
The interval_id byte in the .frm file stores the length of the
888
expression statement for a virtual column.
785
decimals= NOT_FIXED_DEC;
890
vcol_info_length= interval_nr;
895
comment.str= (char*) "";
789
if (fo.scale() > DECIMAL_MAX_SCALE)
900
comment.str= strmake_root(&share->mem_root, comment_pos, comment_length);
901
comment.length= comment_length;
902
comment_pos+= comment_length;
904
if (vcol_info_length)
907
Get virtual column data stored in the .frm file as follows:
908
byte 1 = 1 (always 1 to allow for future extensions)
910
byte 3 = flags (as of now, 0 - no flags, 1 - field is physically stored)
911
byte 4-... = virtual column expression (text data)
913
vcol_info= new virtual_column_info();
914
if ((uint)vcol_screen_pos[0] != 1)
794
decimals= static_cast<uint8_t>(fo.scale());
919
field_type= (enum_field_types) (unsigned char) vcol_screen_pos[1];
920
fld_is_stored= (bool) (uint) vcol_screen_pos[2];
921
vcol_info->expr_str.str= (char *)memdup_root(&share->mem_root,
923
(uint)FRM_VCOL_HEADER_SIZE,
925
(uint)FRM_VCOL_HEADER_SIZE);
926
vcol_info->expr_str.length= vcol_info_length-(uint)FRM_VCOL_HEADER_SIZE;
927
vcol_screen_pos+= vcol_info_length;
798
Item *default_value= NULL;
800
if (pfield.options().has_default_value() ||
801
pfield.options().has_default_null() ||
802
pfield.options().has_default_bin_value())
804
default_value= default_value_item(field_type,
806
pfield.options().default_null(),
807
&pfield.options().default_value(),
808
&pfield.options().default_bin_value());
812
Table temp_table; /* Use this so that BLOB DEFAULT '' works */
813
memset(&temp_table, 0, sizeof(temp_table));
815
temp_table.in_use= &session;
816
temp_table.s->db_low_byte_first= true; //Cursor->low_byte_first();
817
temp_table.s->blob_ptr_size= portable_sizeof_char_ptr;
819
uint32_t field_length= 0; //Assignment is for compiler complaint.
823
case DRIZZLE_TYPE_BLOB:
824
case DRIZZLE_TYPE_VARCHAR:
826
message::Table::Field::StringFieldOptions field_options= pfield.string_options();
828
charset= get_charset(field_options.has_collation_id() ?
829
field_options.collation_id() : 0);
832
charset= default_charset_info;
834
field_length= field_options.length() * charset->mbmaxlen;
837
case DRIZZLE_TYPE_DOUBLE:
839
message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
840
if (!fo.has_precision() && !fo.has_scale())
933
field_length= (uint) strpos[3];
934
recpos= uint2korr(strpos+4),
935
pack_flag= uint2korr(strpos+6);
936
pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files
937
unireg_type= (uint) strpos[8];
938
interval_nr= (uint) strpos[10];
941
field_type= (enum_field_types) f_packtype(pack_flag);
942
if (f_is_binary(pack_flag))
842
field_length= DBL_DIG+7;
945
Try to choose the best 4.1 type:
946
- for 4.0 "CHAR(N) BINARY" or "VARCHAR(N) BINARY"
947
try to find a binary collation for character set.
948
- for other types (e.g. BLOB) just use my_charset_bin.
950
if (!f_is_blob(pack_flag))
952
// 3.23 or 4.0 string
953
if (!(charset= get_charset_by_csname(share->table_charset->csname,
954
MY_CS_BINSORT, MYF(0))))
955
charset= &my_charset_bin;
958
charset= &my_charset_bin;
846
field_length= fo.precision();
848
if (field_length < decimals &&
849
decimals != NOT_FIXED_DEC)
851
my_error(ER_M_BIGGER_THAN_D, MYF(0), pfield.name().c_str());
857
case DRIZZLE_TYPE_DECIMAL:
859
message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
861
field_length= my_decimal_precision_to_length(fo.precision(), fo.scale(),
865
case DRIZZLE_TYPE_TIMESTAMP:
866
case DRIZZLE_TYPE_DATETIME:
867
field_length= DateTime::MAX_STRING_LENGTH;
869
case DRIZZLE_TYPE_DATE:
870
field_length= Date::MAX_STRING_LENGTH;
872
case DRIZZLE_TYPE_ENUM:
876
message::Table::Field::EnumerationValues fo= pfield.enumeration_values();
878
for (int valnr= 0; valnr < fo.field_value_size(); valnr++)
880
if (fo.field_value(valnr).length() > field_length)
882
field_length= charset->cset->numchars(charset,
883
fo.field_value(valnr).c_str(),
884
fo.field_value(valnr).c_str()
885
+ fo.field_value(valnr).length())
891
case DRIZZLE_TYPE_LONG:
893
uint32_t sign_len= pfield.constraints().is_unsigned() ? 0 : 1;
894
field_length= MAX_INT_WIDTH+sign_len;
897
case DRIZZLE_TYPE_LONGLONG:
898
field_length= MAX_BIGINT_WIDTH;
900
case DRIZZLE_TYPE_NULL:
901
abort(); // Programming error
904
Field* f= make_field(share,
906
record + field_offsets[fieldnr] + data_offset,
908
pfield.constraints().is_nullable(),
914
(Field::utype) MTYP_TYPENR(unireg_type),
915
((field_type == DRIZZLE_TYPE_ENUM) ?
916
share->intervals + (interval_nr++)
918
share->fieldnames.type_names[fieldnr]);
920
share->field[fieldnr]= f;
922
f->init(&temp_table); /* blob default values need table obj */
924
if (! (f->flags & NOT_NULL_FLAG))
926
*f->null_ptr|= f->null_bit;
927
if (! (null_bit_pos= (null_bit_pos + 1) & 7)) /* @TODO Ugh. */
961
charset= share->table_charset;
962
memset(&comment, 0, sizeof(comment));
965
if (interval_nr && charset->mbminlen > 1)
967
/* Unescape UCS2 intervals from HEX notation */
968
TYPELIB *interval= share->intervals + interval_nr - 1;
969
unhex_type2(interval);
972
*field_ptr= reg_field=
973
make_field(share, record+recpos,
974
(uint32_t) field_length,
975
null_pos, null_bit_pos,
979
(Field::utype) MTYP_TYPENR(unireg_type),
981
share->intervals+interval_nr-1 :
983
share->fieldnames.type_names[i]);
984
if (!reg_field) // Not supported field type
987
goto err; /* purecov: inspected */
990
reg_field->flags|= ((uint)column_format << COLUMN_FORMAT_FLAGS);
991
reg_field->field_index= i;
992
reg_field->comment=comment;
993
reg_field->vcol_info= vcol_info;
994
reg_field->is_stored= fld_is_stored;
995
if (!(reg_field->flags & NOT_NULL_FLAG))
997
if (!(null_bit_pos= (null_bit_pos + 1) & 7))
934
enum_check_fields old_count_cuted_fields= session.count_cuted_fields;
935
session.count_cuted_fields= CHECK_FIELD_WARN;
936
int res= default_value->save_in_field(f, 1);
937
session.count_cuted_fields= old_count_cuted_fields;
938
if (res != 0 && res != 3) /* @TODO Huh? */
940
my_error(ER_INVALID_DEFAULT, MYF(0), f->field_name);
945
else if (f->real_type() == DRIZZLE_TYPE_ENUM &&
946
(f->flags & NOT_NULL_FLAG))
949
f->store((int64_t) 1, true);
954
/* hack to undo f->init() */
958
f->field_index= fieldnr;
960
if (! default_value &&
961
! (f->unireg_check==Field::NEXT_NUMBER) &&
962
(f->flags & NOT_NULL_FLAG) &&
963
(f->real_type() != DRIZZLE_TYPE_TIMESTAMP))
965
f->flags|= NO_DEFAULT_VALUE_FLAG;
968
if (f->unireg_check == Field::NEXT_NUMBER)
969
share->found_next_number_field= &(share->field[fieldnr]);
971
if (share->timestamp_field == f)
972
share->timestamp_field_offset= fieldnr;
974
if (use_hash) /* supposedly this never fails... but comments lie */
1000
if (f_no_default(pack_flag))
1001
reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
1003
if (reg_field->unireg_check == Field::NEXT_NUMBER)
1004
share->found_next_number_field= field_ptr;
1005
if (share->timestamp_field == reg_field)
1006
share->timestamp_field_offset= i;
975
1009
(void) my_hash_insert(&share->name_hash,
976
(unsigned char*)&(share->field[fieldnr]));
980
keyinfo= share->key_info;
981
for (unsigned int keynr= 0; keynr < share->keys; keynr++, keyinfo++)
983
key_part= keyinfo->key_part;
985
for (unsigned int partnr= 0;
986
partnr < keyinfo->key_parts;
987
partnr++, key_part++)
1010
(unsigned char*) field_ptr); // never fail
1011
if (!reg_field->is_stored)
990
* Fix up key_part->offset by adding data_offset.
991
* We really should compute offset as well.
992
* But at least this way we are a little better.
994
key_part->offset= field_offsets[key_part->fieldnr-1] + data_offset;
1013
share->stored_fields--;
1014
if (share->stored_rec_length>=recpos)
1015
share->stored_rec_length= recpos-1;
999
We need to set the unused bits to 1. If the number of bits is a multiple
1000
of 8 there are no unused bits.
1004
*(record + null_count / 8)|= ~(((unsigned char) 1 << (null_count & 7)) - 1);
1006
share->null_bytes= (null_pos - (unsigned char*) record + (null_bit_pos + 7) / 8);
1008
share->last_null_bit_pos= null_bit_pos;
1010
free(field_offsets);
1011
field_offsets= NULL;
1012
free(field_pack_length);
1013
field_pack_length= NULL;
1016
if (share->key_parts)
1018
*field_ptr=0; // End marker
1019
/* Sanity checks: */
1020
assert(share->fields>=share->stored_fields);
1021
assert(share->reclength>=share->stored_rec_length);
1023
/* Fix key->name and key_part->field */
1018
uint32_t primary_key= (uint32_t) (find_type((char*) "PRIMARY",
1019
&share->keynames, 3) - 1); /* @TODO Huh? */
1026
uint32_t primary_key=(uint) (find_type((char*) "PRIMARY",
1027
&share->keynames, 3) - 1);
1028
int64_t ha_option= handler_file->ha_table_flags();
1021
1029
keyinfo= share->key_info;
1022
1030
key_part= keyinfo->key_part;
1024
for (uint32_t key= 0; key < share->keys; key++,keyinfo++)
1032
for (uint32_t key=0 ; key < share->keys ; key++,keyinfo++)
1026
1034
uint32_t usable_parts= 0;
1035
keyinfo->name=(char*) share->keynames.type_names[key];
1028
1037
if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
1031
If the UNIQUE key doesn't have NULL columns and is not a part key
1032
declare this as a primary key.
1035
for (uint32_t i= 0; i < keyinfo->key_parts; i++)
1037
uint32_t fieldnr= key_part[i].fieldnr;
1039
share->field[fieldnr-1]->null_ptr ||
1040
share->field[fieldnr-1]->key_length() != key_part[i].length)
1042
primary_key= MAX_KEY; // Can't be used
1040
If the UNIQUE key doesn't have NULL columns and is not a part key
1041
declare this as a primary key.
1044
for (i=0 ; i < keyinfo->key_parts ;i++)
1046
uint32_t fieldnr= key_part[i].fieldnr;
1048
share->field[fieldnr-1]->null_ptr ||
1049
share->field[fieldnr-1]->key_length() !=
1052
primary_key=MAX_KEY; // Can't be used
1048
for (uint32_t i= 0 ; i < keyinfo->key_parts ; key_part++,i++)
1058
for (i=0 ; i < keyinfo->key_parts ; key_part++,i++)
1051
if (! key_part->fieldnr)
1061
if (new_field_pack_flag <= 1)
1062
key_part->fieldnr= (uint16_t) find_field(share->field,
1063
share->default_values,
1064
(uint) key_part->offset,
1065
(uint) key_part->length);
1066
if (!key_part->fieldnr)
1053
abort(); // goto err;
1068
error= 4; // Wrong file
1055
1071
field= key_part->field= share->field[key_part->fieldnr-1];
1056
1072
key_part->type= field->key_type();
1057
1073
if (field->null_ptr)
1059
key_part->null_offset=(uint32_t) ((unsigned char*) field->null_ptr -
1075
key_part->null_offset=(uint) ((unsigned char*) field->null_ptr -
1060
1076
share->default_values);
1061
1077
key_part->null_bit= field->null_bit;
1062
1078
key_part->store_length+=HA_KEY_NULL_LENGTH;
1178
1205
/* Store offsets to blob fields to find them fast */
1179
1206
if (!(share->blob_field= save=
1180
1207
(uint*) alloc_root(&share->mem_root,
1181
(uint32_t) (share->blob_fields* sizeof(uint32_t)))))
1208
(uint) (share->blob_fields* sizeof(uint)))))
1183
for (k= 0, ptr= share->field ; *ptr ; ptr++, k++)
1210
for (k=0, ptr= share->field ; *ptr ; ptr++, k++)
1185
1212
if ((*ptr)->flags & BLOB_FLAG)
1190
share->db_low_byte_first= true; // @todo Question this.
1218
the correct null_bytes can now be set, since bitfields have been taken
1221
share->null_bytes= (null_pos - (unsigned char*) null_flags +
1222
(null_bit_pos + 7) / 8);
1223
share->last_null_bit_pos= null_bit_pos;
1225
share->db_low_byte_first= handler_file->low_byte_first();
1191
1226
share->column_bitmap_size= bitmap_buffer_size(share->fields);
1193
my_bitmap_map *bitmaps;
1195
1228
if (!(bitmaps= (my_bitmap_map*) alloc_root(&share->mem_root,
1196
1229
share->column_bitmap_size)))
1198
share->all_set.init(bitmaps, share->fields);
1199
share->all_set.setAll();
1231
bitmap_init(&share->all_set, bitmaps, share->fields, false);
1232
bitmap_set_all(&share->all_set);
1234
delete handler_file;
1205
free(field_offsets);
1206
if (field_pack_length)
1207
free(field_pack_length);
1209
1242
share->error= error;
1210
share->open_errno= errno;
1243
share->open_errno= my_errno;
1244
share->errarg= errarg;
1247
delete handler_file;
1212
1248
hash_free(&share->name_hash);
1213
share->open_table_error(error, share->open_errno, 0);
1219
Read table definition from a binary / text based .frm cursor
1223
session Thread Cursor
1224
share Fill this with table definition
1227
This function is called when the table definition is not cached in
1229
The data is returned in 'share', which is alloced by
1230
alloc_table_share().. The code assumes that share is initialized.
1250
open_table_error(share, error, share->open_errno, errarg);
1252
} /* open_binary_frm */
1256
Clear flag GET_FIXED_FIELDS_FLAG in all fields of the table.
1257
This routine is used for error handling purposes.
1261
table Table object for which virtual columns are set-up
1266
static void clear_field_flag(Table *table)
1270
for (ptr= table->field; *ptr; ptr++)
1271
(*ptr)->flags&= (~GET_FIXED_FIELDS_FLAG);
1275
The function uses the feature in fix_fields where the flag
1276
GET_FIXED_FIELDS_FLAG is set for all fields in the item tree.
1277
This field must always be reset before returning from the function
1278
since it is used for other purposes as well.
1281
fix_fields_vcol_func()
1282
session The thread object
1283
func_item The item tree reference of the virtual columnfunction
1284
table The table object
1285
field_name The name of the processed field
1288
true An error occurred, something was wrong with the
1290
false Ok, a partition field array was created
1293
bool fix_fields_vcol_func(Session *session,
1296
const char *field_name)
1298
uint dir_length, home_dir_length;
1301
TableList *save_table_list, *save_first_table, *save_last_table;
1303
Name_resolution_context *context;
1304
const char *save_where;
1306
char db_name_string[FN_REFLEN];
1307
bool save_use_only_table_context;
1308
Field **ptr, *field;
1309
enum_mark_columns save_mark_used_columns= session->mark_used_columns;
1313
Set-up the TABLE_LIST object to be a list with a single table
1314
Set the object to zero to create NULL pointers and set alias
1315
and real name to table name and get database name from file name.
1318
bzero((void*)&tables, sizeof(TableList));
1319
tables.alias= tables.table_name= (char*) table->s->table_name.str;
1320
tables.table= table;
1321
tables.next_local= NULL;
1322
tables.next_name_resolution_table= NULL;
1323
memcpy(db_name_string,
1324
table->s->normalized_path.str,
1325
table->s->normalized_path.length);
1326
dir_length= dirname_length(db_name_string);
1327
db_name_string[dir_length - 1]= 0;
1328
home_dir_length= dirname_length(db_name_string);
1329
db_name= &db_name_string[home_dir_length];
1332
session->mark_used_columns= MARK_COLUMNS_NONE;
1334
context= session->lex->current_context();
1335
table->map= 1; //To ensure correct calculation of const item
1336
table->get_fields_in_item_tree= true;
1337
save_table_list= context->table_list;
1338
save_first_table= context->first_name_resolution_table;
1339
save_last_table= context->last_name_resolution_table;
1340
context->table_list= &tables;
1341
context->first_name_resolution_table= &tables;
1342
context->last_name_resolution_table= NULL;
1343
func_expr->walk(&Item::change_context_processor, 0, (unsigned char*) context);
1344
save_where= session->where;
1345
session->where= "virtual column function";
1347
/* Save the context before fixing the fields*/
1348
save_use_only_table_context= session->lex->use_only_table_context;
1349
session->lex->use_only_table_context= true;
1350
/* Fix fields referenced to by the virtual column function */
1351
error= func_expr->fix_fields(session, (Item**)0);
1352
/* Restore the original context*/
1353
session->lex->use_only_table_context= save_use_only_table_context;
1354
context->table_list= save_table_list;
1355
context->first_name_resolution_table= save_first_table;
1356
context->last_name_resolution_table= save_last_table;
1358
if (unlikely(error))
1360
clear_field_flag(table);
1363
session->where= save_where;
1365
Walk through the Item tree checking if all items are valid
1366
to be part of the virtual column
1368
error= func_expr->walk(&Item::check_vcol_func_processor, 0, NULL);
1371
my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), field_name);
1372
clear_field_flag(table);
1375
if (unlikely(func_expr->const_item()))
1377
my_error(ER_CONST_EXPR_IN_VCOL, MYF(0));
1378
clear_field_flag(table);
1381
/* Ensure that this virtual column is not based on another virtual field. */
1383
while ((field= *(ptr++)))
1385
if ((field->flags & GET_FIXED_FIELDS_FLAG) &&
1388
my_error(ER_VCOL_BASED_ON_VCOL, MYF(0));
1389
clear_field_flag(table);
1394
Cleanup the fields marked with flag GET_FIXED_FIELDS_FLAG
1395
when calling fix_fields.
1397
clear_field_flag(table);
1401
table->get_fields_in_item_tree= false;
1402
session->mark_used_columns= save_mark_used_columns;
1403
table->map= 0; //Restore old value
1408
Unpack the definition of a virtual column
1411
unpack_vcol_info_from_frm()
1412
session Thread handler
1413
table Table with the checked field
1414
field Pointer to Field object
1415
open_mode Open table mode needed to determine
1416
which errors need to be generated in a failure
1417
error_reported updated flag for the caller that no other error
1418
messages are to be generated.
1234
1 Error (see open_table_error)
1235
2 Error (see open_table_error)
1236
3 Wrong data in .frm cursor
1237
4 Error (see open_table_error)
1238
5 Error (see open_table_error: charset unavailable)
1239
6 Unknown .frm version
1242
int open_table_def(Session& session, TableIdentifier &identifier, TableShare *share)
1424
bool unpack_vcol_info_from_frm(Session *session,
1427
LEX_STRING *vcol_expr,
1428
open_table_mode open_mode,
1429
bool *error_reported)
1250
message::Table table;
1252
error= plugin::StorageEngine::getTableDefinition(session, identifier, table);
1254
if (error != EEXIST)
1263
if (not table.IsInitialized())
1271
error= parse_table_proto(session, table, share);
1273
share->table_category= TABLE_CATEGORY_USER;
1276
if (error && !error_given)
1278
share->error= error;
1279
share->open_table_error(error, (share->open_errno= errno), 0);
1434
Step 1: Construct a statement for the parser.
1435
The parsed string needs to take the following format:
1436
"PARSE_VCOL_EXPR (<expr_string_from_frm>)"
1438
char *vcol_expr_str;
1441
if (!(vcol_expr_str= (char*) alloc_root(&table->mem_root,
1443
parse_vcol_keyword.length + 3)))
1447
memcpy(vcol_expr_str,
1448
(char*) parse_vcol_keyword.str,
1449
parse_vcol_keyword.length);
1450
str_len= parse_vcol_keyword.length;
1451
memcpy(vcol_expr_str + str_len, "(", 1);
1453
memcpy(vcol_expr_str + str_len,
1454
(char*) vcol_expr->str,
1456
str_len+= vcol_expr->length;
1457
memcpy(vcol_expr_str + str_len, ")", 1);
1459
memcpy(vcol_expr_str + str_len, "\0", 1);
1461
Lex_input_stream lip(session, vcol_expr_str, str_len);
1464
Step 2: Setup session for parsing.
1465
1) make Item objects be created in the memory allocated for the Table
1466
object (not TABLE_SHARE)
1467
2) ensure that created Item's are not put on to session->free_list
1468
(which is associated with the parsed statement and hence cleared after
1470
3) setup a flag in the LEX structure to allow "PARSE_VCOL_EXPR"
1471
to be parsed as a SQL command.
1473
MEM_ROOT **root_ptr, *old_root;
1474
Item *backup_free_list= session->free_list;
1475
root_ptr= current_mem_root_ptr();
1476
old_root= *root_ptr;
1477
*root_ptr= &table->mem_root;
1478
session->free_list= NULL;
1479
session->lex->parse_vcol_expr= true;
1482
Step 3: Use the parser to build an Item object from.
1484
if (parse_sql(session, &lip))
1488
/* From now on use vcol_info generated by the parser. */
1489
field->vcol_info= session->lex->vcol_info;
1491
/* Validate the Item tree. */
1492
if (fix_fields_vcol_func(session,
1493
field->vcol_info->expr_item,
1497
if (open_mode == OTM_CREATE)
1500
During CREATE/ALTER TABLE it is ok to receive errors here.
1501
It is not ok if it happens during the opening of an frm
1502
file as part of a normal query.
1504
*error_reported= true;
1506
field->vcol_info= NULL;
1509
field->vcol_info->item_free_list= session->free_list;
1510
session->free_list= backup_free_list;
1511
*root_ptr= old_root;
1516
session->lex->parse_vcol_expr= false;
1517
session->free_items();
1518
*root_ptr= old_root;
1519
session->free_list= backup_free_list;
1287
Open a table based on a TableShare
1525
Open a table based on a TABLE_SHARE
1290
1528
open_table_from_share()
1291
session Thread Cursor
1529
session Thread handler
1292
1530
share Table definition
1293
1531
alias Alias for table
1294
1532
db_stat open flags (for example HA_OPEN_KEYFILE|
1295
1533
HA_OPEN_RNDFILE..) can be 0 (example in
1296
1534
ha_example_table)
1535
prgflag READ_ALL etc..
1297
1536
ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
1298
1537
outparam result table
1538
open_mode One of OTM_OPEN|OTM_CREATE|OTM_ALTER
1539
if OTM_CREATE some errors are ignore
1540
if OTM_ALTER HA_OPEN is not called
1302
1544
1 Error (see open_table_error)
1303
1545
2 Error (see open_table_error)
1304
3 Wrong data in .frm cursor
1546
3 Wrong data in .frm file
1305
1547
4 Error (see open_table_error)
1306
1548
5 Error (see open_table_error: charset unavailable)
1307
1549
7 Table definition has changed in engine
1310
int open_table_from_share(Session *session, TableShare *share, const char *alias,
1311
uint32_t db_stat, uint32_t ha_open_flags,
1552
int open_table_from_share(Session *session, TABLE_SHARE *share, const char *alias,
1553
uint32_t db_stat, uint32_t prgflag, uint32_t ha_open_flags,
1554
Table *outparam, open_table_mode open_mode)
1315
1557
uint32_t records, i, bitmap_size;
1316
1558
bool error_reported= false;
1317
1559
unsigned char *record, *bitmaps;
1560
Field **field_ptr, **vfield_ptr;
1320
1562
/* Parsing of partitioning information from .frm needs session->lex set up. */
1321
1563
assert(session->lex->is_lex_started);
1324
outparam->resetTable(session, share, db_stat);
1327
if (not (outparam->alias= strdup(alias)))
1330
/* Allocate Cursor */
1331
if (not (outparam->cursor= share->db_type()->getCursor(*share, &outparam->mem_root)))
1566
memset(outparam, 0, sizeof(*outparam));
1567
outparam->in_use= session;
1569
outparam->db_stat= db_stat;
1570
outparam->write_row_record= NULL;
1572
init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
1574
if (!(outparam->alias= strdup(alias)))
1576
outparam->quick_keys.init();
1577
outparam->covering_keys.init();
1578
outparam->keys_in_use_for_query.init();
1580
/* Allocate handler */
1582
if (!(prgflag & OPEN_FRM_FILE_ONLY))
1584
if (!(outparam->file= get_new_handler(share, &outparam->mem_root,
1336
if ((db_stat & HA_OPEN_KEYFILE))
1594
outparam->reginfo.lock_type= TL_UNLOCK;
1595
outparam->current_lock= F_UNLCK;
1597
if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN))
1599
if (prgflag & (READ_ALL+EXTRA_RECORD))
1341
1602
if (!(record= (unsigned char*) alloc_root(&outparam->mem_root,
1342
1603
share->rec_buff_length * records)))
1604
goto err; /* purecov: inspected */
1345
1606
if (records == 0)
1987
2626
/* Error if empty or too long column name */
1988
return last_char_is_space || (uint32_t) name_length > NAME_CHAR_LEN;
2627
return last_char_is_space || (uint) name_length > NAME_CHAR_LEN;
2632
Checks whether a table is intact. Should be done *just* after the table has
2635
@param[in] table The table to check
2636
@param[in] table_f_count Expected number of columns in the table
2637
@param[in] table_def Expected structure of the table (column name
2641
@retval TRUE There was an error. An error message is output
2642
to the error log. We do not push an error
2643
message into the error stack because this
2644
function is currently only called at start up,
2645
and such errors never reach the user.
2649
Table::table_check_intact(const uint32_t table_f_count,
2650
const TABLE_FIELD_W_TYPE *table_def)
2654
bool fields_diff_count;
2656
fields_diff_count= (s->fields != table_f_count);
2657
if (fields_diff_count)
2660
/* previous MySQL version */
2661
if (DRIZZLE_VERSION_ID > s->mysql_version)
2663
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE),
2664
alias, table_f_count, s->fields,
2665
s->mysql_version, DRIZZLE_VERSION_ID);
2668
else if (DRIZZLE_VERSION_ID == s->mysql_version)
2670
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), alias,
2671
table_f_count, s->fields);
2675
Something has definitely changed, but we're running an older
2676
version of MySQL with new system tables.
2677
Let's check column definitions. If a column was added at
2678
the end of the table, then we don't care much since such change
2679
is backward compatible.
2682
char buffer[STRING_BUFFER_USUAL_SIZE];
2683
for (i=0 ; i < table_f_count; i++, table_def++)
2685
String sql_type(buffer, sizeof(buffer), system_charset_info);
2689
Field *field= this->field[i];
2691
if (strncmp(field->field_name, table_def->name.str,
2692
table_def->name.length))
2695
Name changes are not fatal, we use ordinal numbers to access columns.
2696
Still this can be a sign of a tampered table, output an error
2699
errmsg_printf(ERRMSG_LVL_ERROR, _("Incorrect definition of table %s.%s: "
2700
"expected column '%s' at position %d, found '%s'."),
2701
s->db.str, alias, table_def->name.str, i,
2704
field->sql_type(sql_type);
2706
Generally, if column types don't match, then something is
2709
However, we only compare column definitions up to the
2710
length of the original definition, since we consider the
2711
following definitions compatible:
2713
1. DATETIME and DATETIM
2714
2. INT(11) and INT(11
2715
3. SET('one', 'two') and SET('one', 'two', 'more')
2717
For SETs or ENUMs, if the same prefix is there it's OK to
2718
add more elements - they will get higher ordinal numbers and
2719
the new table definition is backward compatible with the
2722
if (strncmp(sql_type.c_ptr_safe(), table_def->type.str,
2723
table_def->type.length - 1))
2725
errmsg_printf(ERRMSG_LVL_ERROR, _("Incorrect definition of table %s.%s: "
2726
"expected column '%s' at position %d to have type "
2727
"%s, found type %s."), s->db.str, alias,
2728
table_def->name.str, i, table_def->type.str,
2729
sql_type.c_ptr_safe());
2732
else if (table_def->cset.str && !field->has_charset())
2734
errmsg_printf(ERRMSG_LVL_ERROR, _("Incorrect definition of table %s.%s: "
2735
"expected the type of column '%s' at position %d "
2736
"to have character set '%s' but the type has no "
2737
"character set."), s->db.str, alias,
2738
table_def->name.str, i, table_def->cset.str);
2741
else if (table_def->cset.str &&
2742
strcmp(field->charset()->csname, table_def->cset.str))
2744
errmsg_printf(ERRMSG_LVL_ERROR, _("Incorrect definition of table %s.%s: "
2745
"expected the type of column '%s' at position %d "
2746
"to have character set '%s' but found "
2747
"character set '%s'."), s->db.str, alias,
2748
table_def->name.str, i, table_def->cset.str,
2749
field->charset()->csname);
2755
errmsg_printf(ERRMSG_LVL_ERROR, _("Incorrect definition of table %s.%s: "
2756
"expected column '%s' at position %d to have type %s "
2757
" but the column is not found."),
2759
table_def->name.str, i, table_def->type.str);
2768
Create Item_field for each column in the table.
2771
Table::fill_item_list()
2772
item_list a pointer to an empty list used to store items
2775
Create Item_field object for each column in the table and
2776
initialize it with the corresponding Field. New items are
2777
created in the current Session memory root.
2784
bool Table::fill_item_list(List<Item> *item_list) const
2787
All Item_field's created using a direct pointer to a field
2788
are fixed in Item_field constructor.
2790
for (Field **ptr= field; *ptr; ptr++)
2792
Item_field *item= new Item_field(*ptr);
2793
if (!item || item_list->push_back(item))
2800
Reset an existing list of Item_field items to point to the
2801
Fields of this table.
2804
Table::fill_item_list()
2805
item_list a non-empty list with Item_fields
2808
This is a counterpart of fill_item_list used to redirect
2809
Item_fields to the fields of a newly created table.
2810
The caller must ensure that number of items in the item_list
2811
is the same as the number of columns in the table.
2814
void Table::reset_item_list(List<Item> *item_list) const
2816
List_iterator_fast<Item> it(*item_list);
2817
for (Field **ptr= field; *ptr; ptr++)
2819
Item_field *item_field= (Item_field*) it++;
2820
assert(item_field != 0);
2821
item_field->reset_field(*ptr);
2827
Find underlying base tables (TableList) which represent given
2828
table_to_find (Table)
2831
TableList::find_underlying_table()
2832
table_to_find table to find
2835
0 table is not found
2836
found table reference
2839
TableList *TableList::find_underlying_table(Table *table_to_find)
2841
/* is this real table and table which we are looking for? */
2842
if (table == table_to_find && merge_underlying_list == 0)
2845
for (TableList *tbl= merge_underlying_list; tbl; tbl= tbl->next_local)
2848
if ((result= tbl->find_underlying_table(table_to_find)))
2855
cleunup items belonged to view fields translation table
2858
TableList::cleanup_items()
2861
void TableList::cleanup_items()
2866
bool TableList::placeholder()
2868
return derived || schema_table || (create && !table->getDBStat()) || !table;
2873
Set insert_values buffer
2877
mem_root memory pool for allocating
2881
TRUE - out of memory
2884
bool TableList::set_insert_values(MEM_ROOT *mem_root)
2888
if (!table->insert_values &&
2889
!(table->insert_values= (unsigned char *)alloc_root(mem_root,
2890
table->s->rec_buff_length)))
2899
Test if this is a leaf with respect to name resolution.
2902
TableList::is_leaf_for_name_resolution()
2905
A table reference is a leaf with respect to name resolution if
2906
it is either a leaf node in a nested join tree (table, view,
2907
schema table, subquery), or an inner node that represents a
2908
NATURAL/USING join, or a nested join with materialized join
2912
TRUE if a leaf, false otherwise.
2914
bool TableList::is_leaf_for_name_resolution()
2916
return (is_natural_join || is_join_columns_complete || !nested_join);
2921
Retrieve the first (left-most) leaf in a nested join tree with
2922
respect to name resolution.
2925
TableList::first_leaf_for_name_resolution()
2928
Given that 'this' is a nested table reference, recursively walk
2929
down the left-most children of 'this' until we reach a leaf
2930
table reference with respect to name resolution.
2933
The left-most child of a nested table reference is the last element
2934
in the list of children because the children are inserted in
2938
If 'this' is a nested table reference - the left-most child of
2939
the tree rooted in 'this',
2943
TableList *TableList::first_leaf_for_name_resolution()
2945
TableList *cur_table_ref= NULL;
2946
nested_join_st *cur_nested_join;
2948
if (is_leaf_for_name_resolution())
2950
assert(nested_join);
2952
for (cur_nested_join= nested_join;
2954
cur_nested_join= cur_table_ref->nested_join)
2956
List_iterator_fast<TableList> it(cur_nested_join->join_list);
2957
cur_table_ref= it++;
2959
If the current nested join is a RIGHT JOIN, the operands in
2960
'join_list' are in reverse order, thus the first operand is
2961
already at the front of the list. Otherwise the first operand
2962
is in the end of the list of join operands.
2964
if (!(cur_table_ref->outer_join & JOIN_TYPE_RIGHT))
2967
while ((next= it++))
2968
cur_table_ref= next;
2970
if (cur_table_ref->is_leaf_for_name_resolution())
2973
return cur_table_ref;
2978
Retrieve the last (right-most) leaf in a nested join tree with
2979
respect to name resolution.
2982
TableList::last_leaf_for_name_resolution()
2985
Given that 'this' is a nested table reference, recursively walk
2986
down the right-most children of 'this' until we reach a leaf
2987
table reference with respect to name resolution.
2990
The right-most child of a nested table reference is the first
2991
element in the list of children because the children are inserted
2995
- If 'this' is a nested table reference - the right-most child of
2996
the tree rooted in 'this',
3000
TableList *TableList::last_leaf_for_name_resolution()
3002
TableList *cur_table_ref= this;
3003
nested_join_st *cur_nested_join;
3005
if (is_leaf_for_name_resolution())
3007
assert(nested_join);
3009
for (cur_nested_join= nested_join;
3011
cur_nested_join= cur_table_ref->nested_join)
3013
cur_table_ref= cur_nested_join->join_list.head();
3015
If the current nested is a RIGHT JOIN, the operands in
3016
'join_list' are in reverse order, thus the last operand is in the
3019
if ((cur_table_ref->outer_join & JOIN_TYPE_RIGHT))
3021
List_iterator_fast<TableList> it(cur_nested_join->join_list);
3023
cur_table_ref= it++;
3024
while ((next= it++))
3025
cur_table_ref= next;
3027
if (cur_table_ref->is_leaf_for_name_resolution())
3030
return cur_table_ref;