1404
1434
/****************************************************************************/
1406
void Table::column_bitmaps_set(boost::dynamic_bitset<>& read_set_arg,
1407
boost::dynamic_bitset<>& write_set_arg)
1409
read_set= &read_set_arg;
1410
write_set= &write_set_arg;
1414
const boost::dynamic_bitset<> Table::use_all_columns(boost::dynamic_bitset<>& in_map)
1416
const boost::dynamic_bitset<> old= in_map;
1417
in_map= getShare()->all_set;
1437
Create a reduced Table object with properly set up Field list from a
1438
list of field definitions.
1440
The created table doesn't have a table Cursor associated with
1441
it, has no keys, no group/distinct, no copy_funcs array.
1442
The sole purpose of this Table object is to use the power of Field
1443
class to read/write data to/from table->record[0]. Then one can store
1444
the record in any container (RB tree, hash, etc).
1445
The table is created in Session mem_root, so are the table's fields.
1446
Consequently, if you don't BLOB fields, you don't need to free it.
1448
@param session connection handle
1449
@param field_list list of column definitions
1452
0 if out of memory, Table object in case of success
1455
Table *Session::create_virtual_tmp_table(List<CreateField> &field_list)
1457
uint32_t field_count= field_list.elements;
1458
uint32_t blob_count= 0;
1460
CreateField *cdef; /* column definition */
1461
uint32_t record_length= 0;
1462
uint32_t null_count= 0; /* number of columns which may be null */
1463
uint32_t null_pack_length; /* NULL representation array length */
1464
unsigned char *bitmaps;
1467
TableShareInstance *share= getTemporaryShare(message::Table::INTERNAL); // This will not go into the tableshare cache, so no key is used.
1469
if (! share->getMemRoot()->multi_alloc_root(0,
1470
&bitmaps, bitmap_buffer_size(field_count)*2,
1476
table= share->getTable();
1477
share->setFields(field_count + 1);
1478
table->setFields(share->getFields(true));
1479
field= share->getFields(true);
1480
share->blob_field.resize(field_count+1);
1481
share->fields= field_count;
1482
share->blob_ptr_size= portable_sizeof_char_ptr;
1483
table->setup_tmp_table_column_bitmaps(bitmaps);
1485
table->in_use= this; /* field->reset() may access table->in_use */
1487
/* Create all fields and calculate the total length of record */
1488
List_iterator_fast<CreateField> it(field_list);
1489
while ((cdef= it++))
1491
*field= share->make_field(NULL,
1493
(cdef->flags & NOT_NULL_FLAG) ? false : true,
1494
(unsigned char *) ((cdef->flags & NOT_NULL_FLAG) ? 0 : ""),
1495
(cdef->flags & NOT_NULL_FLAG) ? 0 : 1,
1504
(*field)->init(table);
1505
record_length+= (*field)->pack_length();
1506
if (! ((*field)->flags & NOT_NULL_FLAG))
1509
if ((*field)->flags & BLOB_FLAG)
1510
share->blob_field[blob_count++]= (uint32_t) (field - table->getFields());
1514
*field= NULL; /* mark the end of the list */
1515
share->blob_field[blob_count]= 0; /* mark the end of the list */
1516
share->blob_fields= blob_count;
1518
null_pack_length= (null_count + 7)/8;
1519
share->setRecordLength(record_length + null_pack_length);
1520
share->rec_buff_length= ALIGN_SIZE(share->getRecordLength() + 1);
1521
table->record[0]= (unsigned char*)alloc(share->rec_buff_length);
1522
if (!table->record[0])
1525
if (null_pack_length)
1527
table->null_flags= (unsigned char*) table->record[0];
1528
share->null_fields= null_count;
1529
share->null_bytes= null_pack_length;
1532
/* Set up field pointers */
1533
unsigned char *null_pos= table->record[0];
1534
unsigned char *field_pos= null_pos + share->null_bytes;
1535
uint32_t null_bit= 1;
1537
for (field= table->getFields(); *field; ++field)
1539
Field *cur_field= *field;
1540
if ((cur_field->flags & NOT_NULL_FLAG))
1541
cur_field->move_field(field_pos);
1544
cur_field->move_field(field_pos, (unsigned char*) null_pos, null_bit);
1546
if (null_bit == (1 << 8))
1554
field_pos+= cur_field->pack_length();
1561
for (field= table->getFields(); *field; ++field)
1563
delete *field; /* just invokes field destructor */
1568
bool Table::open_tmp_table()
1572
TableIdentifier identifier(s->getSchemaName(), s->getTableName(), s->getPath());
1573
if ((error=cursor->ha_open(identifier,
1577
HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
1579
print_error(error, MYF(0));
1583
(void) cursor->extra(HA_EXTRA_QUICK); /* Faster */
1589
Create MyISAM temporary table
1592
create_myisam_tmp_table()
1593
keyinfo Description of the index (there is always one index)
1594
start_recinfo MyISAM's column descriptions
1595
recinfo INOUT End of MyISAM's column descriptions
1599
Create a MyISAM temporary table according to passed description. The is
1600
assumed to have one unique index or constraint.
1602
The passed array or MI_COLUMNDEF structures must have this form:
1604
1. 1-byte column (afaiu for 'deleted' flag) (note maybe not 1-byte
1605
when there are many nullable columns)
1607
3. One free MI_COLUMNDEF element (*recinfo points here)
1609
This function may use the free element to create hash column for unique
1617
bool Table::create_myisam_tmp_table(KeyInfo *keyinfo,
1618
MI_COLUMNDEF *start_recinfo,
1619
MI_COLUMNDEF **recinfo,
1624
MI_UNIQUEDEF uniquedef;
1625
TableShare *share= s;
1627
if (share->sizeKeys())
1628
{ // Get keys for ni_create
1629
bool using_unique_constraint= false;
1630
HA_KEYSEG *seg= (HA_KEYSEG*) this->mem_root.alloc_root(sizeof(*seg) * keyinfo->key_parts);
1634
memset(seg, 0, sizeof(*seg) * keyinfo->key_parts);
1635
if (keyinfo->key_length >= cursor->getEngine()->max_key_length() ||
1636
keyinfo->key_parts > cursor->getEngine()->max_key_parts() ||
1639
/* Can't create a key; Make a unique constraint instead of a key */
1642
using_unique_constraint= true;
1643
memset(&uniquedef, 0, sizeof(uniquedef));
1644
uniquedef.keysegs=keyinfo->key_parts;
1646
uniquedef.null_are_equal=1;
1648
/* Create extra column for hash value */
1649
memset(*recinfo, 0, sizeof(**recinfo));
1650
(*recinfo)->type= FIELD_CHECK;
1651
(*recinfo)->length=MI_UNIQUE_HASH_LENGTH;
1653
share->setRecordLength(share->getRecordLength() + MI_UNIQUE_HASH_LENGTH);
1657
/* Create an unique key */
1658
memset(&keydef, 0, sizeof(keydef));
1659
keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
1660
keydef.keysegs= keyinfo->key_parts;
1663
for (uint32_t i= 0; i < keyinfo->key_parts ; i++,seg++)
1665
Field *key_field=keyinfo->key_part[i].field;
1667
seg->language= key_field->charset()->number;
1668
seg->length= keyinfo->key_part[i].length;
1669
seg->start= keyinfo->key_part[i].offset;
1670
if (key_field->flags & BLOB_FLAG)
1672
seg->type= ((keyinfo->key_part[i].key_type & 1 /* binary */) ?
1673
HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
1674
seg->bit_start= (uint8_t)(key_field->pack_length()
1675
- share->blob_ptr_size);
1676
seg->flag= HA_BLOB_PART;
1677
seg->length= 0; // Whole blob in unique constraint
1681
seg->type= keyinfo->key_part[i].type;
1683
if (!(key_field->flags & NOT_NULL_FLAG))
1685
seg->null_bit= key_field->null_bit;
1686
seg->null_pos= (uint32_t) (key_field->null_ptr - (unsigned char*) record[0]);
1688
We are using a GROUP BY on something that contains NULL
1689
In this case we have to tell MyISAM that two NULL should
1690
on INSERT be regarded at the same value
1692
if (! using_unique_constraint)
1693
keydef.flag|= HA_NULL_ARE_EQUAL;
1697
MI_CREATE_INFO create_info;
1698
memset(&create_info, 0, sizeof(create_info));
1700
if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
1702
create_info.data_file_length= ~(uint64_t) 0;
1704
if ((error=mi_create(share->getTableName(), share->sizeKeys(), &keydef,
1705
(uint32_t) (*recinfo-start_recinfo),
1707
share->uniques, &uniquedef,
1709
HA_CREATE_TMP_TABLE)))
1711
print_error(error, MYF(0));
1715
status_var_increment(in_use->status_var.created_tmp_disk_tables);
1716
share->db_record_offset= 1;
1723
void Table::free_tmp_table(Session *session)
1725
memory::Root own_root= mem_root;
1726
const char *save_proc_info;
1728
save_proc_info= session->get_proc_info();
1729
session->set_proc_info("removing tmp table");
1731
// Release latches since this can take a long time
1732
plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
1738
cursor->closeMarkForDelete(s->getTableName());
1741
TableIdentifier identifier(s->getSchemaName(), s->getTableName(), s->getTableName());
1742
s->db_type()->doDropTable(*session, identifier);
1748
for (Field **ptr= field ; *ptr ; ptr++)
1754
own_root.free_root(MYF(0)); /* the table is allocated in its own root */
1755
session->set_proc_info(save_proc_info);
1758
my_bitmap_map *Table::use_all_columns(MyBitmap *bitmap)
1760
my_bitmap_map *old= bitmap->getBitmap();
1761
bitmap->setBitmap(s->all_set.getBitmap());
1421
void Table::restore_column_map(const boost::dynamic_bitset<>& old)
1765
void Table::restore_column_map(my_bitmap_map *old)
1423
for (boost::dynamic_bitset<>::size_type i= 0; i < old.size(); i++)
1767
read_set->setBitmap(old);
1436
1770
uint32_t Table::find_shortest_key(const key_map *usable_keys)
1467
1801
for (; *ptr ; ptr++)
1469
if ((*ptr)->cmp_offset(getShare()->rec_buff_length))
1803
if ((*ptr)->cmp_offset(s->rec_buff_length))
1476
True if the table's input and output record buffers are comparable using
1477
compare_records(TABLE*).
1479
bool Table::records_are_comparable()
1481
return ((getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ) == 0) ||
1482
write_set->is_subset_of(*read_set));
1486
Compares the input and outbut record buffers of the table to see if a row
1487
has changed. The algorithm iterates over updated columns and if they are
1488
nullable compares NULL bits in the buffer before comparing actual
1489
data. Special care must be taken to compare only the relevant NULL bits and
1490
mask out all others as they may be undefined. The storage engine will not
1491
and should not touch them.
1493
@param table The table to evaluate.
1495
@return true if row has changed.
1496
@return false otherwise.
1498
bool Table::compare_records()
1500
if (getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ) != 0)
1503
Storage engine may not have read all columns of the record. Fields
1504
(including NULL bits) not in the write_set may not have been read and
1505
can therefore not be compared.
1507
for (Field **ptr= this->field ; *ptr != NULL; ptr++)
1510
if (write_set->test(f->position()))
1512
if (f->real_maybe_null())
1514
unsigned char null_byte_index= f->null_ptr - record[0];
1516
if (((record[0][null_byte_index]) & f->null_bit) !=
1517
((record[1][null_byte_index]) & f->null_bit))
1520
if (f->cmp_binary_offset(getShare()->rec_buff_length))
1528
The storage engine has read all columns, so it's safe to compare all bits
1529
including those not in the write_set. This is cheaper than the
1530
field-by-field comparison done above.
1532
if (not getShare()->blob_fields + getShare()->hasVariableWidth())
1533
// Fixed-size record: do bitwise comparison of the records
1534
return memcmp(this->getInsertRecord(), this->getUpdateRecord(), (size_t) getShare()->getRecordLength());
1809
/* Return false if row hasn't changed */
1811
bool Table::compare_record()
1813
if (s->blob_fields + s->varchar_fields == 0)
1814
return memcmp(this->record[0], this->record[1], (size_t) s->getRecordLength());
1536
1816
/* Compare null bits */
1537
if (memcmp(null_flags, null_flags + getShare()->rec_buff_length, getShare()->null_bytes))
1817
if (memcmp(null_flags, null_flags + s->rec_buff_length, s->null_bytes))
1538
1818
return true; /* Diff in NULL value */
1540
1820
/* Compare updated fields */
1541
1821
for (Field **ptr= field ; *ptr ; ptr++)
1543
if (isWriteSet((*ptr)->position()) &&
1544
(*ptr)->cmp_binary_offset(getShare()->rec_buff_length))
1823
if (isWriteSet((*ptr)->field_index) &&
1824
(*ptr)->cmp_binary_offset(s->rec_buff_length))