~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table.cc

  • Committer: David Shrewsbury
  • Date: 2010-10-11 17:20:14 UTC
  • mfrom: (1838 trunk-drizzle)
  • mto: (1838.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 1839.
  • Revision ID: shrewsbury.dave@gmail.com-20101011172014-sij1m2doi2fl2duo
Merge from trunk and resolve conflicts

Show diffs side-by-side

added added

removed removed

Lines of Context:
54
54
#include <drizzled/item/null.h>
55
55
#include <drizzled/temporal.h>
56
56
 
57
 
#include "drizzled/table/instance.h"
 
57
#include "drizzled/table_share_instance.h"
58
58
 
59
59
#include "drizzled/table_proto.h"
60
60
 
81
81
 
82
82
  if (db_stat)
83
83
    error= cursor->close();
84
 
  _alias.clear();
 
84
  free((char*) alias);
 
85
  alias= NULL;
85
86
  if (field)
86
87
  {
87
88
    for (Field **ptr=field ; *ptr ; ptr++)
95
96
 
96
97
  if (free_share)
97
98
  {
98
 
    release();
 
99
    if (getShare()->getType() == message::Table::STANDARD)
 
100
    {
 
101
      TableShare::release(getMutableShare());
 
102
    }
 
103
    else
 
104
    {
 
105
      delete getShare();
 
106
    }
 
107
 
 
108
    setShare(NULL);
99
109
  }
 
110
  mem_root.free_root(MYF(0));
100
111
 
101
112
  return error;
102
113
}
103
114
 
104
 
Table::~Table()
105
 
{
106
 
  mem_root.free_root(MYF(0));
107
 
}
108
 
 
109
115
 
110
116
void Table::resetTable(Session *session,
111
117
                       TableShare *share,
136
142
 
137
143
  pos_in_table_list= NULL;
138
144
  group= NULL;
139
 
  _alias.clear();
 
145
  alias= NULL;
140
146
  null_flags= NULL;
141
147
 
142
148
  lock_position= 0;
247
253
  return (nr);
248
254
} /* set_zone */
249
255
 
 
256
        /* Adjust number to next larger disk buffer */
 
257
 
 
258
ulong next_io_size(register ulong pos)
 
259
{
 
260
  register ulong offset;
 
261
  if ((offset= pos & (IO_SIZE-1)))
 
262
    return pos-offset+IO_SIZE;
 
263
  return pos;
 
264
} /* next_io_size */
 
265
 
250
266
 
251
267
/*
252
268
  Store an SQL quoted string.
310
326
}
311
327
 
312
328
 
 
329
/*
 
330
  Set up column usage bitmaps for a temporary table
 
331
 
 
332
  IMPLEMENTATION
 
333
    For temporary tables, we need one bitmap with all columns set and
 
334
    a tmp_set bitmap to be used by things like filesort.
 
335
*/
 
336
 
 
337
void Table::setup_tmp_table_column_bitmaps()
 
338
{
 
339
  uint32_t field_count= getShare()->sizeFields();
 
340
 
 
341
  this->def_read_set.resize(field_count);
 
342
  this->def_write_set.resize(field_count);
 
343
  this->tmp_set.resize(field_count);
 
344
  this->getMutableShare()->all_set.resize(field_count);
 
345
  this->getMutableShare()->all_set.set();
 
346
  this->def_write_set.set();
 
347
  this->def_read_set.set();
 
348
  default_column_bitmaps();
 
349
}
 
350
 
 
351
 
313
352
int rename_file_ext(const char * from,const char * to,const char * ext)
314
353
{
315
354
  string from_s, to_s;
521
560
    We must set bit in read set as update_auto_increment() is using the
522
561
    store() to check overflow of auto_increment values
523
562
  */
524
 
  setReadSet(found_next_number_field->position());
525
 
  setWriteSet(found_next_number_field->position());
 
563
  setReadSet(found_next_number_field->field_index);
 
564
  setWriteSet(found_next_number_field->field_index);
526
565
  if (getShare()->next_number_keypart)
527
566
    mark_columns_used_by_index_no_reset(getShare()->next_number_index);
528
567
}
571
610
    for (reg_field= field ; *reg_field ; reg_field++)
572
611
    {
573
612
      if ((*reg_field)->flags & PART_KEY_FLAG)
574
 
        setReadSet((*reg_field)->position());
 
613
        setReadSet((*reg_field)->field_index);
575
614
    }
576
615
  }
577
616
}
620
659
    {
621
660
      /* Merge keys is all keys that had a column refered to in the query */
622
661
      if (is_overlapping(merge_keys, (*reg_field)->part_of_key))
623
 
        setReadSet((*reg_field)->position());
 
662
        setReadSet((*reg_field)->field_index);
624
663
    }
625
664
  }
626
665
 
658
697
  return length;
659
698
}
660
699
 
661
 
void Table::setVariableWidth(void)
662
 
{
663
 
  assert(in_use);
664
 
  if (in_use && in_use->lex->sql_command == SQLCOM_CREATE_TABLE)
665
 
  {
666
 
    getMutableShare()->setVariableWidth();
667
 
    return;
668
 
  }
669
 
 
670
 
  assert(0); // Programming error, you can't set this on a plain old Table.
671
 
}
672
 
 
673
700
/****************************************************************************
674
701
 Functions for creating temporary tables.
675
702
****************************************************************************/
707
734
  */
708
735
  if (convert_blob_length && convert_blob_length <= Field_varstring::MAX_SIZE &&
709
736
      (org_field->flags & BLOB_FLAG))
710
 
  {
711
 
    table->setVariableWidth();
712
737
    new_field= new Field_varstring(convert_blob_length,
713
738
                                   org_field->maybe_null(),
714
 
                                   org_field->field_name,
 
739
                                   org_field->field_name, table->getMutableShare(),
715
740
                                   org_field->charset());
716
 
  }
717
741
  else
718
 
  {
719
742
    new_field= org_field->new_field(session->mem_root, table,
720
743
                                    table == org_field->getTable());
721
 
  }
722
744
  if (new_field)
723
745
  {
724
746
    new_field->init(table);
771
793
 
772
794
Table *
773
795
create_tmp_table(Session *session,Tmp_Table_Param *param,List<Item> &fields,
774
 
                 Order *group, bool distinct, bool save_sum_fields,
 
796
                 order_st *group, bool distinct, bool save_sum_fields,
775
797
                 uint64_t select_options, ha_rows rows_limit,
776
798
                 const char *table_alias)
777
799
{
778
800
  memory::Root *mem_root_save;
 
801
  Table *table;
779
802
  uint  i,field_count,null_count,null_pack_length;
780
803
  uint32_t  copy_func_count= param->func_count;
781
804
  uint32_t  hidden_null_count, hidden_null_pack_length, hidden_field_count;
805
828
    {
806
829
      group= 0;                                 // Can't use group key
807
830
    }
808
 
    else for (Order *tmp=group ; tmp ; tmp=tmp->next)
 
831
    else for (order_st *tmp=group ; tmp ; tmp=tmp->next)
809
832
    {
810
833
      /*
811
834
        marker == 4 means two things:
838
861
    copy_func_count+= param->sum_func_count;
839
862
  }
840
863
 
841
 
  table::Instance *table;
842
 
  table= session->getInstanceTable(); // This will not go into the tableshare cache, so no key is used.
 
864
  table= session->getTemporaryShare(message::Table::INTERNAL); // This will not go into the tableshare cache, so no key is used.
843
865
 
844
866
  if (not table->getMemRoot()->multi_alloc_root(0,
845
867
                                                &default_field, sizeof(Field*) * (field_count),
871
893
  table->getMutableShare()->setFields(field_count+1);
872
894
  table->setFields(table->getMutableShare()->getFields(true));
873
895
  reg_field= table->getMutableShare()->getFields(true);
874
 
  table->setAlias(table_alias);
 
896
  table->alias= table_alias;
875
897
  table->reginfo.lock_type=TL_WRITE;    /* Will be updated */
876
898
  table->db_stat=HA_OPEN_KEYFILE+HA_OPEN_RNDFILE;
877
899
  table->map=1;
965
987
            */
966
988
            (*argp)->maybe_null=1;
967
989
          }
968
 
          new_field->setPosition(fieldnr++);
 
990
          new_field->field_index= fieldnr++;
969
991
        }
970
992
      }
971
993
    }
1012
1034
        group_null_items++;
1013
1035
        new_field->flags|= GROUP_FLAG;
1014
1036
      }
1015
 
      new_field->setPosition(fieldnr++);
 
1037
      new_field->field_index= fieldnr++;
1016
1038
      *(reg_field++)= new_field;
1017
1039
    }
1018
1040
    if (!--hidden_field_count)
1045
1067
      (select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) == OPTION_BIG_TABLES)
1046
1068
  {
1047
1069
    table->getMutableShare()->storage_engine= myisam_engine;
1048
 
    table->cursor= table->getMutableShare()->db_type()->getCursor(*table);
 
1070
    table->cursor= table->getMutableShare()->db_type()->getCursor(*table->getMutableShare());
1049
1071
    if (group &&
1050
1072
        (param->group_parts > table->cursor->getEngine()->max_key_parts() ||
1051
1073
         param->group_length > table->cursor->getEngine()->max_key_length()))
1056
1078
  else
1057
1079
  {
1058
1080
    table->getMutableShare()->storage_engine= heap_engine;
1059
 
    table->cursor= table->getMutableShare()->db_type()->getCursor(*table);
 
1081
    table->cursor= table->getMutableShare()->db_type()->getCursor(*table->getMutableShare());
1060
1082
  }
1061
1083
  if (! table->cursor)
1062
1084
    goto err;
1238
1260
    keyinfo->rec_per_key= 0;
1239
1261
    keyinfo->algorithm= HA_KEY_ALG_UNDEF;
1240
1262
    keyinfo->name= (char*) "group_key";
1241
 
    Order *cur_group= group;
 
1263
    order_st *cur_group= group;
1242
1264
    for (; cur_group ; cur_group= cur_group->next, key_part_info++)
1243
1265
    {
1244
1266
      Field *field=(*cur_group->item)->get_tmp_table_field();
1329
1351
      key_part_info->null_bit= 0;
1330
1352
      key_part_info->offset=hidden_null_pack_length;
1331
1353
      key_part_info->length=null_pack_length;
1332
 
      table->setVariableWidth();
1333
1354
      key_part_info->field= new Field_varstring(table->getInsertRecord(),
1334
1355
                                                (uint32_t) key_part_info->length,
1335
1356
                                                0,
1336
1357
                                                (unsigned char*) 0,
1337
1358
                                                (uint32_t) 0,
1338
1359
                                                NULL,
 
1360
                                                table->getMutableShare(),
1339
1361
                                                &my_charset_bin);
1340
1362
      if (!key_part_info->field)
1341
1363
        goto err;
1380
1402
  if (session->is_fatal_error)                          // If end of memory
1381
1403
    goto err;
1382
1404
  table->getMutableShare()->db_record_offset= 1;
1383
 
  if (table->getShare()->db_type() == myisam_engine)
 
1405
  if (table->getMutableShare()->db_type() == myisam_engine)
1384
1406
  {
1385
1407
    if (table->create_myisam_tmp_table(param->keyinfo, param->start_recinfo,
1386
1408
                                       &param->recinfo, select_options))
1403
1425
 
1404
1426
/****************************************************************************/
1405
1427
 
 
1428
/**
 
1429
  Create a reduced Table object with properly set up Field list from a
 
1430
  list of field definitions.
 
1431
 
 
1432
    The created table doesn't have a table Cursor associated with
 
1433
    it, has no keys, no group/distinct, no copy_funcs array.
 
1434
    The sole purpose of this Table object is to use the power of Field
 
1435
    class to read/write data to/from table->getInsertRecord(). Then one can store
 
1436
    the record in any container (RB tree, hash, etc).
 
1437
    The table is created in Session mem_root, so are the table's fields.
 
1438
    Consequently, if you don't BLOB fields, you don't need to free it.
 
1439
 
 
1440
  @param session         connection handle
 
1441
  @param field_list  list of column definitions
 
1442
 
 
1443
  @return
 
1444
    0 if out of memory, Table object in case of success
 
1445
*/
 
1446
 
 
1447
Table *Session::create_virtual_tmp_table(List<CreateField> &field_list)
 
1448
{
 
1449
  uint32_t field_count= field_list.elements;
 
1450
  uint32_t blob_count= 0;
 
1451
  Field **field;
 
1452
  CreateField *cdef;                           /* column definition */
 
1453
  uint32_t record_length= 0;
 
1454
  uint32_t null_count= 0;                 /* number of columns which may be null */
 
1455
  uint32_t null_pack_length;              /* NULL representation array length */
 
1456
 
 
1457
  Table *table= getTemporaryShare(message::Table::INTERNAL); // This will not go into the tableshare cache, so no key is used.
 
1458
  table->getMutableShare()->setFields(field_count + 1);
 
1459
  table->setFields(table->getMutableShare()->getFields(true));
 
1460
  field= table->getMutableShare()->getFields(true);
 
1461
  table->getMutableShare()->blob_field.resize(field_count+1);
 
1462
  table->getMutableShare()->fields= field_count;
 
1463
  table->getMutableShare()->blob_ptr_size= portable_sizeof_char_ptr;
 
1464
  table->setup_tmp_table_column_bitmaps();
 
1465
 
 
1466
  table->in_use= this;           /* field->reset() may access table->in_use */
 
1467
 
 
1468
  /* Create all fields and calculate the total length of record */
 
1469
  List_iterator_fast<CreateField> it(field_list);
 
1470
  while ((cdef= it++))
 
1471
  {
 
1472
    *field= table->getMutableShare()->make_field(NULL,
 
1473
                                                 cdef->length,
 
1474
                                                 (cdef->flags & NOT_NULL_FLAG) ? false : true,
 
1475
                                                 (unsigned char *) ((cdef->flags & NOT_NULL_FLAG) ? 0 : ""),
 
1476
                                                 (cdef->flags & NOT_NULL_FLAG) ? 0 : 1,
 
1477
                                                 cdef->decimals,
 
1478
                                                 cdef->sql_type,
 
1479
                                                 cdef->charset,
 
1480
                                                 cdef->unireg_check,
 
1481
                                                 cdef->interval,
 
1482
                                                 cdef->field_name);
 
1483
    if (!*field)
 
1484
      goto error;
 
1485
    (*field)->init(table);
 
1486
    record_length+= (*field)->pack_length();
 
1487
    if (! ((*field)->flags & NOT_NULL_FLAG))
 
1488
      null_count++;
 
1489
 
 
1490
    if ((*field)->flags & BLOB_FLAG)
 
1491
      table->getMutableShare()->blob_field[blob_count++]= (uint32_t) (field - table->getFields());
 
1492
 
 
1493
    field++;
 
1494
  }
 
1495
  *field= NULL;                             /* mark the end of the list */
 
1496
  table->getMutableShare()->blob_field[blob_count]= 0;            /* mark the end of the list */
 
1497
  table->getMutableShare()->blob_fields= blob_count;
 
1498
 
 
1499
  null_pack_length= (null_count + 7)/8;
 
1500
  table->getMutableShare()->setRecordLength(record_length + null_pack_length);
 
1501
  table->getMutableShare()->rec_buff_length= ALIGN_SIZE(table->getMutableShare()->getRecordLength() + 1);
 
1502
  table->record[0]= (unsigned char*)alloc(table->getMutableShare()->rec_buff_length);
 
1503
  if (not table->getInsertRecord())
 
1504
    goto error;
 
1505
 
 
1506
  if (null_pack_length)
 
1507
  {
 
1508
    table->null_flags= (unsigned char*) table->getInsertRecord();
 
1509
    table->getMutableShare()->null_fields= null_count;
 
1510
    table->getMutableShare()->null_bytes= null_pack_length;
 
1511
  }
 
1512
  {
 
1513
    /* Set up field pointers */
 
1514
    unsigned char *null_pos= table->getInsertRecord();
 
1515
    unsigned char *field_pos= null_pos + table->getMutableShare()->null_bytes;
 
1516
    uint32_t null_bit= 1;
 
1517
 
 
1518
    for (field= table->getFields(); *field; ++field)
 
1519
    {
 
1520
      Field *cur_field= *field;
 
1521
      if ((cur_field->flags & NOT_NULL_FLAG))
 
1522
        cur_field->move_field(field_pos);
 
1523
      else
 
1524
      {
 
1525
        cur_field->move_field(field_pos, (unsigned char*) null_pos, null_bit);
 
1526
        null_bit<<= 1;
 
1527
        if (null_bit == (1 << 8))
 
1528
        {
 
1529
          ++null_pos;
 
1530
          null_bit= 1;
 
1531
        }
 
1532
      }
 
1533
      cur_field->reset();
 
1534
 
 
1535
      field_pos+= cur_field->pack_length();
 
1536
    }
 
1537
  }
 
1538
 
 
1539
  return table;
 
1540
 
 
1541
error:
 
1542
  for (field= table->getFields(); *field; ++field)
 
1543
  {
 
1544
    delete *field;                         /* just invokes field destructor */
 
1545
  }
 
1546
  return 0;
 
1547
}
 
1548
 
 
1549
bool Table::open_tmp_table()
 
1550
{
 
1551
  int error;
 
1552
  
 
1553
  TableIdentifier identifier(getShare()->getSchemaName(), getShare()->getTableName(), getShare()->getPath());
 
1554
  if ((error=cursor->ha_open(identifier,
 
1555
                             this,
 
1556
                             O_RDWR,
 
1557
                             HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
 
1558
  {
 
1559
    print_error(error, MYF(0));
 
1560
    db_stat= 0;
 
1561
    return true;
 
1562
  }
 
1563
  (void) cursor->extra(HA_EXTRA_QUICK);         /* Faster */
 
1564
  return false;
 
1565
}
 
1566
 
 
1567
 
 
1568
/*
 
1569
  Create MyISAM temporary table
 
1570
 
 
1571
  SYNOPSIS
 
1572
    create_myisam_tmp_table()
 
1573
      keyinfo         Description of the index (there is always one index)
 
1574
      start_recinfo   MyISAM's column descriptions
 
1575
      recinfo INOUT   End of MyISAM's column descriptions
 
1576
      options         Option bits
 
1577
 
 
1578
  DESCRIPTION
 
1579
    Create a MyISAM temporary table according to passed description. The is
 
1580
    assumed to have one unique index or constraint.
 
1581
 
 
1582
    The passed array or MI_COLUMNDEF structures must have this form:
 
1583
 
 
1584
      1. 1-byte column (afaiu for 'deleted' flag) (note maybe not 1-byte
 
1585
         when there are many nullable columns)
 
1586
      2. Table columns
 
1587
      3. One free MI_COLUMNDEF element (*recinfo points here)
 
1588
 
 
1589
    This function may use the free element to create hash column for unique
 
1590
    constraint.
 
1591
 
 
1592
   RETURN
 
1593
     false - OK
 
1594
     true  - Error
 
1595
*/
 
1596
 
 
1597
bool Table::create_myisam_tmp_table(KeyInfo *keyinfo,
 
1598
                                    MI_COLUMNDEF *start_recinfo,
 
1599
                                    MI_COLUMNDEF **recinfo,
 
1600
                                    uint64_t options)
 
1601
{
 
1602
  int error;
 
1603
  MI_KEYDEF keydef;
 
1604
  MI_UNIQUEDEF uniquedef;
 
1605
 
 
1606
  if (getShare()->sizeKeys())
 
1607
  {                                             // Get keys for ni_create
 
1608
    bool using_unique_constraint= false;
 
1609
    HA_KEYSEG *seg= (HA_KEYSEG*) this->mem_root.alloc_root(sizeof(*seg) * keyinfo->key_parts);
 
1610
    if (not seg)
 
1611
      return true;
 
1612
 
 
1613
    memset(seg, 0, sizeof(*seg) * keyinfo->key_parts);
 
1614
    if (keyinfo->key_length >= cursor->getEngine()->max_key_length() ||
 
1615
        keyinfo->key_parts > cursor->getEngine()->max_key_parts() ||
 
1616
        getShare()->uniques)
 
1617
    {
 
1618
      /* Can't create a key; Make a unique constraint instead of a key */
 
1619
      getMutableShare()->keys=    0;
 
1620
      getMutableShare()->uniques= 1;
 
1621
      using_unique_constraint= true;
 
1622
      memset(&uniquedef, 0, sizeof(uniquedef));
 
1623
      uniquedef.keysegs=keyinfo->key_parts;
 
1624
      uniquedef.seg=seg;
 
1625
      uniquedef.null_are_equal=1;
 
1626
 
 
1627
      /* Create extra column for hash value */
 
1628
      memset(*recinfo, 0, sizeof(**recinfo));
 
1629
      (*recinfo)->type= FIELD_CHECK;
 
1630
      (*recinfo)->length=MI_UNIQUE_HASH_LENGTH;
 
1631
      (*recinfo)++;
 
1632
      getMutableShare()->setRecordLength(getShare()->getRecordLength() + MI_UNIQUE_HASH_LENGTH);
 
1633
    }
 
1634
    else
 
1635
    {
 
1636
      /* Create an unique key */
 
1637
      memset(&keydef, 0, sizeof(keydef));
 
1638
      keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
 
1639
      keydef.keysegs=  keyinfo->key_parts;
 
1640
      keydef.seg= seg;
 
1641
    }
 
1642
    for (uint32_t i= 0; i < keyinfo->key_parts ; i++,seg++)
 
1643
    {
 
1644
      Field *key_field=keyinfo->key_part[i].field;
 
1645
      seg->flag=     0;
 
1646
      seg->language= key_field->charset()->number;
 
1647
      seg->length=   keyinfo->key_part[i].length;
 
1648
      seg->start=    keyinfo->key_part[i].offset;
 
1649
      if (key_field->flags & BLOB_FLAG)
 
1650
      {
 
1651
        seg->type= ((keyinfo->key_part[i].key_type & 1 /* binary */) ?
 
1652
         HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
 
1653
        seg->bit_start= (uint8_t)(key_field->pack_length() - getShare()->blob_ptr_size);
 
1654
        seg->flag= HA_BLOB_PART;
 
1655
        seg->length= 0;                 // Whole blob in unique constraint
 
1656
      }
 
1657
      else
 
1658
      {
 
1659
        seg->type= keyinfo->key_part[i].type;
 
1660
      }
 
1661
      if (!(key_field->flags & NOT_NULL_FLAG))
 
1662
      {
 
1663
        seg->null_bit= key_field->null_bit;
 
1664
        seg->null_pos= (uint32_t) (key_field->null_ptr - (unsigned char*) getInsertRecord());
 
1665
        /*
 
1666
          We are using a GROUP BY on something that contains NULL
 
1667
          In this case we have to tell MyISAM that two NULL should
 
1668
          on INSERT be regarded at the same value
 
1669
        */
 
1670
        if (! using_unique_constraint)
 
1671
          keydef.flag|= HA_NULL_ARE_EQUAL;
 
1672
      }
 
1673
    }
 
1674
  }
 
1675
  MI_CREATE_INFO create_info;
 
1676
 
 
1677
  if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
 
1678
      OPTION_BIG_TABLES)
 
1679
    create_info.data_file_length= ~(uint64_t) 0;
 
1680
 
 
1681
  if ((error= mi_create(getShare()->getTableName(), getShare()->sizeKeys(), &keydef,
 
1682
                        (uint32_t) (*recinfo-start_recinfo),
 
1683
                        start_recinfo,
 
1684
                        getShare()->uniques, &uniquedef,
 
1685
                        &create_info,
 
1686
                        HA_CREATE_TMP_TABLE)))
 
1687
  {
 
1688
    print_error(error, MYF(0));
 
1689
    db_stat= 0;
 
1690
 
 
1691
    return true;
 
1692
  }
 
1693
  in_use->status_var.created_tmp_disk_tables++;
 
1694
  getMutableShare()->db_record_offset= 1;
 
1695
  return false;
 
1696
}
 
1697
 
 
1698
 
 
1699
void Table::free_tmp_table(Session *session)
 
1700
{
 
1701
  memory::Root own_root= mem_root;
 
1702
  const char *save_proc_info;
 
1703
 
 
1704
  save_proc_info= session->get_proc_info();
 
1705
  session->set_proc_info("removing tmp table");
 
1706
 
 
1707
  // Release latches since this can take a long time
 
1708
  plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
 
1709
 
 
1710
  if (cursor)
 
1711
  {
 
1712
    if (db_stat)
 
1713
    {
 
1714
      cursor->closeMarkForDelete(getShare()->getTableName());
 
1715
    }
 
1716
 
 
1717
    TableIdentifier identifier(getShare()->getSchemaName(), getShare()->getTableName(), getShare()->getTableName());
 
1718
    getMutableShare()->db_type()->doDropTable(*session, identifier);
 
1719
 
 
1720
    delete cursor;
 
1721
  }
 
1722
 
 
1723
  /* free blobs */
 
1724
  for (Field **ptr= field ; *ptr ; ptr++)
 
1725
  {
 
1726
    (*ptr)->free();
 
1727
  }
 
1728
  free_io_cache();
 
1729
 
 
1730
  own_root.free_root(MYF(0)); /* the table is allocated in its own root */
 
1731
  session->set_proc_info(save_proc_info);
 
1732
}
 
1733
 
1406
1734
void Table::column_bitmaps_set(boost::dynamic_bitset<>& read_set_arg,
1407
1735
                               boost::dynamic_bitset<>& write_set_arg)
1408
1736
{
1472
1800
  return false;
1473
1801
}
1474
1802
 
1475
 
/**
1476
 
   True if the table's input and output record buffers are comparable using
1477
 
   compare_records(TABLE*).
1478
 
 */
1479
 
bool Table::records_are_comparable()
1480
 
{
1481
 
  return ((getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ) == 0) ||
1482
 
          write_set->is_subset_of(*read_set));
1483
 
}
1484
 
 
1485
 
/**
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.
1492
 
 
1493
 
   @param table The table to evaluate.
1494
 
 
1495
 
   @return true if row has changed.
1496
 
   @return false otherwise.
1497
 
*/
1498
 
bool Table::compare_records()
1499
 
{
1500
 
  if (getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ) != 0)
1501
 
  {
1502
 
    /*
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.
1506
 
    */
1507
 
    for (Field **ptr= this->field ; *ptr != NULL; ptr++)
1508
 
    {
1509
 
      Field *f= *ptr;
1510
 
      if (write_set->test(f->position()))
1511
 
      {
1512
 
        if (f->real_maybe_null())
1513
 
        {
1514
 
          unsigned char null_byte_index= f->null_ptr - record[0];
1515
 
 
1516
 
          if (((record[0][null_byte_index]) & f->null_bit) !=
1517
 
              ((record[1][null_byte_index]) & f->null_bit))
1518
 
            return true;
1519
 
        }
1520
 
        if (f->cmp_binary_offset(getShare()->rec_buff_length))
1521
 
          return true;
1522
 
      }
1523
 
    }
1524
 
    return false;
1525
 
  }
1526
 
 
1527
 
  /*
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.
1531
 
  */
1532
 
  if (not getShare()->blob_fields + getShare()->hasVariableWidth())
1533
 
    // Fixed-size record: do bitwise comparison of the records
 
1803
/* Return false if row hasn't changed */
 
1804
 
 
1805
bool Table::compare_record()
 
1806
{
 
1807
  if (getShare()->blob_fields + getShare()->varchar_fields == 0)
1534
1808
    return memcmp(this->getInsertRecord(), this->getUpdateRecord(), (size_t) getShare()->getRecordLength());
1535
 
 
 
1809
  
1536
1810
  /* Compare null bits */
1537
1811
  if (memcmp(null_flags, null_flags + getShare()->rec_buff_length, getShare()->null_bytes))
1538
1812
    return true; /* Diff in NULL value */
1540
1814
  /* Compare updated fields */
1541
1815
  for (Field **ptr= field ; *ptr ; ptr++)
1542
1816
  {
1543
 
    if (isWriteSet((*ptr)->position()) &&
 
1817
    if (isWriteSet((*ptr)->field_index) &&
1544
1818
        (*ptr)->cmp_binary_offset(getShare()->rec_buff_length))
1545
1819
      return true;
1546
1820
  }
1604
1878
}
1605
1879
 
1606
1880
Table::Table() : 
 
1881
  _share(NULL),
1607
1882
  field(NULL),
1608
1883
  cursor(NULL),
1609
1884
  next(NULL),
1622
1897
  timestamp_field(NULL),
1623
1898
  pos_in_table_list(NULL),
1624
1899
  group(NULL),
 
1900
  alias(NULL),
1625
1901
  null_flags(NULL),
1626
1902
  lock_position(0),
1627
1903
  lock_data_start(0),
1647
1923
  query_id(0),
1648
1924
  quick_condition_rows(0),
1649
1925
  timestamp_field_type(TIMESTAMP_NO_AUTO_SET),
1650
 
  map(0)
 
1926
  map(0),
 
1927
  is_placeholder_created(0)
1651
1928
{
1652
1929
  record[0]= (unsigned char *) 0;
1653
1930
  record[1]= (unsigned char *) 0;
1731
2008
  return false;
1732
2009
}
1733
2010
 
1734
 
 
1735
 
void Table::filesort_free_buffers(bool full)
1736
 
{
1737
 
  if (sort.record_pointers)
1738
 
  {
1739
 
    free((unsigned char*) sort.record_pointers);
1740
 
    sort.record_pointers=0;
1741
 
  }
1742
 
  if (full)
1743
 
  {
1744
 
    if (sort.sort_keys )
1745
 
    {
1746
 
      if ((unsigned char*) sort.sort_keys)
1747
 
        free((unsigned char*) sort.sort_keys);
1748
 
      sort.sort_keys= 0;
1749
 
    }
1750
 
    if (sort.buffpek)
1751
 
    {
1752
 
      if ((unsigned char*) sort.buffpek)
1753
 
        free((unsigned char*) sort.buffpek);
1754
 
      sort.buffpek= 0;
1755
 
      sort.buffpek_len= 0;
1756
 
    }
1757
 
  }
1758
 
 
1759
 
  if (sort.addon_buf)
1760
 
  {
1761
 
    free((char *) sort.addon_buf);
1762
 
    free((char *) sort.addon_field);
1763
 
    sort.addon_buf=0;
1764
 
    sort.addon_field=0;
1765
 
  }
1766
 
}
1767
 
 
1768
2011
} /* namespace drizzled */