1404
1420
/****************************************************************************/
1423
Create a reduced Table object with properly set up Field list from a
1424
list of field definitions.
1426
The created table doesn't have a table Cursor associated with
1427
it, has no keys, no group/distinct, no copy_funcs array.
1428
The sole purpose of this Table object is to use the power of Field
1429
class to read/write data to/from table->getInsertRecord(). Then one can store
1430
the record in any container (RB tree, hash, etc).
1431
The table is created in Session mem_root, so are the table's fields.
1432
Consequently, if you don't BLOB fields, you don't need to free it.
1434
@param session connection handle
1435
@param field_list list of column definitions
1438
0 if out of memory, Table object in case of success
1441
Table *Session::create_virtual_tmp_table(List<CreateField> &field_list)
1443
uint32_t field_count= field_list.elements;
1444
uint32_t blob_count= 0;
1446
CreateField *cdef; /* column definition */
1447
uint32_t record_length= 0;
1448
uint32_t null_count= 0; /* number of columns which may be null */
1449
uint32_t null_pack_length; /* NULL representation array length */
1451
table::Instance *table= getInstanceTable(); // This will not go into the tableshare cache, so no key is used.
1452
table->getMutableShare()->setFields(field_count + 1);
1453
table->setFields(table->getMutableShare()->getFields(true));
1454
field= table->getMutableShare()->getFields(true);
1455
table->getMutableShare()->blob_field.resize(field_count+1);
1456
table->getMutableShare()->fields= field_count;
1457
table->getMutableShare()->blob_ptr_size= portable_sizeof_char_ptr;
1458
table->setup_tmp_table_column_bitmaps();
1460
table->in_use= this; /* field->reset() may access table->in_use */
1462
/* Create all fields and calculate the total length of record */
1463
List_iterator_fast<CreateField> it(field_list);
1464
while ((cdef= it++))
1466
*field= table->getMutableShare()->make_field(NULL,
1468
(cdef->flags & NOT_NULL_FLAG) ? false : true,
1469
(unsigned char *) ((cdef->flags & NOT_NULL_FLAG) ? 0 : ""),
1470
(cdef->flags & NOT_NULL_FLAG) ? 0 : 1,
1479
(*field)->init(table);
1480
record_length+= (*field)->pack_length();
1481
if (! ((*field)->flags & NOT_NULL_FLAG))
1484
if ((*field)->flags & BLOB_FLAG)
1485
table->getMutableShare()->blob_field[blob_count++]= (uint32_t) (field - table->getFields());
1489
*field= NULL; /* mark the end of the list */
1490
table->getMutableShare()->blob_field[blob_count]= 0; /* mark the end of the list */
1491
table->getMutableShare()->blob_fields= blob_count;
1493
null_pack_length= (null_count + 7)/8;
1494
table->getMutableShare()->setRecordLength(record_length + null_pack_length);
1495
table->getMutableShare()->rec_buff_length= ALIGN_SIZE(table->getMutableShare()->getRecordLength() + 1);
1496
table->record[0]= (unsigned char*)alloc(table->getMutableShare()->rec_buff_length);
1497
if (not table->getInsertRecord())
1500
if (null_pack_length)
1502
table->null_flags= (unsigned char*) table->getInsertRecord();
1503
table->getMutableShare()->null_fields= null_count;
1504
table->getMutableShare()->null_bytes= null_pack_length;
1507
/* Set up field pointers */
1508
unsigned char *null_pos= table->getInsertRecord();
1509
unsigned char *field_pos= null_pos + table->getMutableShare()->null_bytes;
1510
uint32_t null_bit= 1;
1512
for (field= table->getFields(); *field; ++field)
1514
Field *cur_field= *field;
1515
if ((cur_field->flags & NOT_NULL_FLAG))
1516
cur_field->move_field(field_pos);
1519
cur_field->move_field(field_pos, (unsigned char*) null_pos, null_bit);
1521
if (null_bit == (1 << 8))
1529
field_pos+= cur_field->pack_length();
1536
for (field= table->getFields(); *field; ++field)
1538
delete *field; /* just invokes field destructor */
1406
1543
void Table::column_bitmaps_set(boost::dynamic_bitset<>& read_set_arg,
1407
1544
boost::dynamic_bitset<>& write_set_arg)
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.
1612
/* Return false if row hasn't changed */
1614
bool Table::compare_record()
1532
1616
if (not getShare()->blob_fields + getShare()->hasVariableWidth())
1533
// Fixed-size record: do bitwise comparison of the records
1534
1617
return memcmp(this->getInsertRecord(), this->getUpdateRecord(), (size_t) getShare()->getRecordLength());
1536
1619
/* Compare null bits */
1537
1620
if (memcmp(null_flags, null_flags + getShare()->rec_buff_length, getShare()->null_bytes))
1538
1621
return true; /* Diff in NULL value */