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()
1571
if ((error=cursor->ha_open(this, s->getTableName(),O_RDWR,
1572
HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
1574
print_error(error, MYF(0));
1578
(void) cursor->extra(HA_EXTRA_QUICK); /* Faster */
1584
Create MyISAM temporary table
1587
create_myisam_tmp_table()
1588
keyinfo Description of the index (there is always one index)
1589
start_recinfo MyISAM's column descriptions
1590
recinfo INOUT End of MyISAM's column descriptions
1594
Create a MyISAM temporary table according to passed description. The is
1595
assumed to have one unique index or constraint.
1597
The passed array or MI_COLUMNDEF structures must have this form:
1599
1. 1-byte column (afaiu for 'deleted' flag) (note maybe not 1-byte
1600
when there are many nullable columns)
1602
3. One free MI_COLUMNDEF element (*recinfo points here)
1604
This function may use the free element to create hash column for unique
1612
bool Table::create_myisam_tmp_table(KeyInfo *keyinfo,
1613
MI_COLUMNDEF *start_recinfo,
1614
MI_COLUMNDEF **recinfo,
1619
MI_UNIQUEDEF uniquedef;
1620
TableShare *share= s;
1622
if (share->sizeKeys())
1623
{ // Get keys for ni_create
1624
bool using_unique_constraint= false;
1625
HA_KEYSEG *seg= (HA_KEYSEG*) this->mem_root.alloc_root(sizeof(*seg) * keyinfo->key_parts);
1629
memset(seg, 0, sizeof(*seg) * keyinfo->key_parts);
1630
if (keyinfo->key_length >= cursor->getEngine()->max_key_length() ||
1631
keyinfo->key_parts > cursor->getEngine()->max_key_parts() ||
1634
/* Can't create a key; Make a unique constraint instead of a key */
1637
using_unique_constraint= true;
1638
memset(&uniquedef, 0, sizeof(uniquedef));
1639
uniquedef.keysegs=keyinfo->key_parts;
1641
uniquedef.null_are_equal=1;
1643
/* Create extra column for hash value */
1644
memset(*recinfo, 0, sizeof(**recinfo));
1645
(*recinfo)->type= FIELD_CHECK;
1646
(*recinfo)->length=MI_UNIQUE_HASH_LENGTH;
1648
share->setRecordLength(share->getRecordLength() + MI_UNIQUE_HASH_LENGTH);
1652
/* Create an unique key */
1653
memset(&keydef, 0, sizeof(keydef));
1654
keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
1655
keydef.keysegs= keyinfo->key_parts;
1658
for (uint32_t i= 0; i < keyinfo->key_parts ; i++,seg++)
1660
Field *key_field=keyinfo->key_part[i].field;
1662
seg->language= key_field->charset()->number;
1663
seg->length= keyinfo->key_part[i].length;
1664
seg->start= keyinfo->key_part[i].offset;
1665
if (key_field->flags & BLOB_FLAG)
1667
seg->type= ((keyinfo->key_part[i].key_type & 1 /* binary */) ?
1668
HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
1669
seg->bit_start= (uint8_t)(key_field->pack_length()
1670
- share->blob_ptr_size);
1671
seg->flag= HA_BLOB_PART;
1672
seg->length= 0; // Whole blob in unique constraint
1676
seg->type= keyinfo->key_part[i].type;
1678
if (!(key_field->flags & NOT_NULL_FLAG))
1680
seg->null_bit= key_field->null_bit;
1681
seg->null_pos= (uint32_t) (key_field->null_ptr - (unsigned char*) record[0]);
1683
We are using a GROUP BY on something that contains NULL
1684
In this case we have to tell MyISAM that two NULL should
1685
on INSERT be regarded at the same value
1687
if (! using_unique_constraint)
1688
keydef.flag|= HA_NULL_ARE_EQUAL;
1692
MI_CREATE_INFO create_info;
1693
memset(&create_info, 0, sizeof(create_info));
1695
if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
1697
create_info.data_file_length= ~(uint64_t) 0;
1699
if ((error=mi_create(share->getTableName(), share->sizeKeys(), &keydef,
1700
(uint32_t) (*recinfo-start_recinfo),
1702
share->uniques, &uniquedef,
1704
HA_CREATE_TMP_TABLE)))
1706
print_error(error, MYF(0));
1710
status_var_increment(in_use->status_var.created_tmp_disk_tables);
1711
share->db_record_offset= 1;
1718
void Table::free_tmp_table(Session *session)
1720
memory::Root own_root= mem_root;
1721
const char *save_proc_info;
1723
save_proc_info= session->get_proc_info();
1724
session->set_proc_info("removing tmp table");
1726
// Release latches since this can take a long time
1727
plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
1733
cursor->closeMarkForDelete(s->getTableName());
1736
TableIdentifier identifier(s->getSchemaName(), s->getTableName(), s->getTableName());
1737
s->db_type()->doDropTable(*session, identifier);
1743
for (Field **ptr= field ; *ptr ; ptr++)
1749
own_root.free_root(MYF(0)); /* the table is allocated in its own root */
1750
session->set_proc_info(save_proc_info);
1753
my_bitmap_map *Table::use_all_columns(MyBitmap *bitmap)
1755
my_bitmap_map *old= bitmap->getBitmap();
1756
bitmap->setBitmap(s->all_set.getBitmap());
1421
void Table::restore_column_map(const boost::dynamic_bitset<>& old)
1760
void Table::restore_column_map(my_bitmap_map *old)
1423
for (boost::dynamic_bitset<>::size_type i= 0; i < old.size(); i++)
1762
read_set->setBitmap(old);
1436
1765
uint32_t Table::find_shortest_key(const key_map *usable_keys)
1467
1796
for (; *ptr ; ptr++)
1469
if ((*ptr)->cmp_offset(getShare()->rec_buff_length))
1798
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());
1804
/* Return false if row hasn't changed */
1806
bool Table::compare_record()
1808
if (s->blob_fields + s->varchar_fields == 0)
1809
return memcmp(this->record[0], this->record[1], (size_t) s->getRecordLength());
1536
1811
/* Compare null bits */
1537
if (memcmp(null_flags, null_flags + getShare()->rec_buff_length, getShare()->null_bytes))
1812
if (memcmp(null_flags, null_flags + s->rec_buff_length, s->null_bytes))
1538
1813
return true; /* Diff in NULL value */
1540
1815
/* Compare updated fields */
1541
1816
for (Field **ptr= field ; *ptr ; ptr++)
1543
if (isWriteSet((*ptr)->position()) &&
1544
(*ptr)->cmp_binary_offset(getShare()->rec_buff_length))
1818
if (isWriteSet((*ptr)->field_index) &&
1819
(*ptr)->cmp_binary_offset(s->rec_buff_length))