~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table.cc

  • Committer: Padraig O'Sullivan
  • Date: 2010-12-03 19:16:09 UTC
  • mto: (1975.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 1976.
  • Revision ID: osullivan.padraig@gmail.com-20101203191609-7s81iwt33vrgmz9v
Some re-factoring based on feedback from Monty on IRC.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
/* Some general useful functions */
18
18
 
19
 
#include <config.h>
 
19
#include "config.h"
20
20
 
21
21
#include <float.h>
22
22
#include <fcntl.h>
28
28
#include <drizzled/error.h>
29
29
#include <drizzled/gettext.h>
30
30
 
31
 
#include <drizzled/plugin/transactional_storage_engine.h>
32
 
#include <drizzled/plugin/authorization.h>
 
31
#include "drizzled/plugin/transactional_storage_engine.h"
 
32
#include "drizzled/plugin/authorization.h"
33
33
#include <drizzled/nested_join.h>
34
34
#include <drizzled/sql_parse.h>
35
35
#include <drizzled/item/sum.h>
42
42
#include <drizzled/field/double.h>
43
43
#include <drizzled/unireg.h>
44
44
#include <drizzled/message/table.pb.h>
45
 
#include <drizzled/sql_table.h>
46
 
#include <drizzled/charset.h>
47
 
#include <drizzled/internal/m_string.h>
48
 
#include <plugin/myisam/myisam.h>
49
 
#include <drizzled/plugin/storage_engine.h>
 
45
#include "drizzled/sql_table.h"
 
46
#include "drizzled/charset.h"
 
47
#include "drizzled/internal/m_string.h"
 
48
#include "plugin/myisam/myisam.h"
50
49
 
51
50
#include <drizzled/item/string.h>
52
51
#include <drizzled/item/int.h>
55
54
#include <drizzled/item/null.h>
56
55
#include <drizzled/temporal.h>
57
56
 
58
 
#include <drizzled/refresh_version.h>
59
 
 
60
 
#include <drizzled/table/singular.h>
61
 
 
62
 
#include <drizzled/table_proto.h>
63
 
#include <drizzled/typelib.h>
 
57
#include "drizzled/table/instance.h"
 
58
 
 
59
#include "drizzled/table_proto.h"
64
60
 
65
61
using namespace std;
66
62
 
67
63
namespace drizzled
68
64
{
69
65
 
 
66
extern pid_t current_pid;
70
67
extern plugin::StorageEngine *heap_engine;
71
68
extern plugin::StorageEngine *myisam_engine;
72
69
 
73
70
/* Functions defined in this cursor */
74
71
 
 
72
void open_table_error(TableShare *share, int error, int db_errno,
 
73
                      myf errortype, int errarg);
 
74
 
75
75
/*************************************************************************/
76
76
 
77
77
// @note this should all be the destructor
82
82
  if (db_stat)
83
83
    error= cursor->close();
84
84
  _alias.clear();
85
 
 
86
85
  if (field)
87
86
  {
88
87
    for (Field **ptr=field ; *ptr ; ptr++)
91
90
    }
92
91
    field= 0;
93
92
  }
94
 
  safe_delete(cursor);
 
93
  delete cursor;
 
94
  cursor= 0;                            /* For easier errorchecking */
95
95
 
96
96
  if (free_share)
97
97
  {
112
112
                       uint32_t db_stat_arg)
113
113
{
114
114
  setShare(share);
115
 
  in_use= session;
116
 
 
117
115
  field= NULL;
118
116
 
119
117
  cursor= NULL;
126
124
  tablenr= 0;
127
125
  db_stat= db_stat_arg;
128
126
 
 
127
  in_use= session;
129
128
  record[0]= (unsigned char *) NULL;
130
129
  record[1]= (unsigned char *) NULL;
131
130
 
197
196
 
198
197
/* Deallocate temporary blob storage */
199
198
 
200
 
void free_blobs(Table *table)
 
199
void free_blobs(register Table *table)
201
200
{
202
201
  uint32_t *ptr, *end;
203
202
  for (ptr= table->getBlobField(), end=ptr + table->sizeBlobFields();
223
222
    
224
223
  result->type_lengths= (uint*) (result->type_names + result->count + 1);
225
224
 
226
 
  List<String>::iterator it(strings.begin());
 
225
  List_iterator<String> it(strings);
227
226
  String *tmp;
228
227
  for (uint32_t i= 0; (tmp= it++); i++)
229
228
  {
239
238
 
240
239
        /* Check that the integer is in the internal */
241
240
 
242
 
int set_zone(int nr, int min_zone, int max_zone)
 
241
int set_zone(register int nr, int min_zone, int max_zone)
243
242
{
244
243
  if (nr<=min_zone)
245
244
    return (min_zone);
323
322
}
324
323
 
325
324
/*
 
325
  Check if database name is valid
 
326
 
 
327
  SYNPOSIS
 
328
    check_db_name()
 
329
    org_name            Name of database and length
 
330
 
 
331
  RETURN
 
332
    false error
 
333
    true ok
 
334
*/
 
335
 
 
336
bool check_db_name(Session *session, SchemaIdentifier &schema_identifier)
 
337
{
 
338
  if (not plugin::Authorization::isAuthorized(session->getSecurityContext(), schema_identifier))
 
339
  {
 
340
    return false;
 
341
  }
 
342
 
 
343
  return schema_identifier.isValid();
 
344
}
 
345
 
 
346
/*
326
347
  Allow anything as a table name, as long as it doesn't contain an
327
348
  ' ' at the end
328
349
  returns 1 on error
500
521
    We must set bit in read set as update_auto_increment() is using the
501
522
    store() to check overflow of auto_increment values
502
523
  */
503
 
  setReadSet(found_next_number_field->position());
504
 
  setWriteSet(found_next_number_field->position());
 
524
  setReadSet(found_next_number_field->field_index);
 
525
  setWriteSet(found_next_number_field->field_index);
505
526
  if (getShare()->next_number_keypart)
506
527
    mark_columns_used_by_index_no_reset(getShare()->next_number_index);
507
528
}
550
571
    for (reg_field= field ; *reg_field ; reg_field++)
551
572
    {
552
573
      if ((*reg_field)->flags & PART_KEY_FLAG)
553
 
        setReadSet((*reg_field)->position());
 
574
        setReadSet((*reg_field)->field_index);
554
575
    }
555
576
  }
556
577
}
599
620
    {
600
621
      /* Merge keys is all keys that had a column refered to in the query */
601
622
      if (is_overlapping(merge_keys, (*reg_field)->part_of_key))
602
 
        setReadSet((*reg_field)->position());
 
623
        setReadSet((*reg_field)->field_index);
603
624
    }
604
625
  }
605
626
 
640
661
void Table::setVariableWidth(void)
641
662
{
642
663
  assert(in_use);
643
 
  if (in_use && in_use->getLex()->sql_command == SQLCOM_CREATE_TABLE)
 
664
  if (in_use && in_use->lex->sql_command == SQLCOM_CREATE_TABLE)
644
665
  {
645
666
    getMutableShare()->setVariableWidth();
646
667
    return;
817
838
    copy_func_count+= param->sum_func_count;
818
839
  }
819
840
 
820
 
  table::Singular *table;
 
841
  table::Instance *table;
821
842
  table= session->getInstanceTable(); // This will not go into the tableshare cache, so no key is used.
822
843
 
823
844
  if (not table->getMemRoot()->multi_alloc_root(0,
863
884
 
864
885
  table->getMutableShare()->blob_field.resize(field_count+1);
865
886
  uint32_t *blob_field= &table->getMutableShare()->blob_field[0];
 
887
  table->getMutableShare()->blob_ptr_size= portable_sizeof_char_ptr;
866
888
  table->getMutableShare()->db_low_byte_first=1;                // True for HEAP and MyISAM
867
889
  table->getMutableShare()->table_charset= param->table_charset;
868
890
  table->getMutableShare()->keys_for_keyread.reset();
874
896
  blob_count= string_count= null_count= hidden_null_count= group_null_items= 0;
875
897
  param->using_indirect_summary_function= 0;
876
898
 
877
 
  List<Item>::iterator li(fields.begin());
 
899
  List_iterator_fast<Item> li(fields);
878
900
  Item *item;
879
901
  Field **tmp_from_field=from_field;
880
902
  while ((item=li++))
943
965
            */
944
966
            (*argp)->maybe_null=1;
945
967
          }
946
 
          new_field->setPosition(fieldnr++);
 
968
          new_field->field_index= fieldnr++;
947
969
        }
948
970
      }
949
971
    }
990
1012
        group_null_items++;
991
1013
        new_field->flags|= GROUP_FLAG;
992
1014
      }
993
 
      new_field->setPosition(fieldnr++);
 
1015
      new_field->field_index= fieldnr++;
994
1016
      *(reg_field++)= new_field;
995
1017
    }
996
1018
    if (!--hidden_field_count)
1013
1035
  field_count= fieldnr;
1014
1036
  *reg_field= 0;
1015
1037
  *blob_field= 0;                               // End marker
1016
 
  table->getMutableShare()->setFieldSize(field_count);
 
1038
  table->getMutableShare()->fields= field_count;
1017
1039
 
1018
1040
  /* If result table is small; use a heap */
1019
1041
  /* future: storage engine selection can be made dynamic? */
1020
1042
  if (blob_count || using_unique_constraint || 
1021
 
      (session->getLex()->select_lex.options & SELECT_BIG_RESULT) ||
1022
 
      (session->getLex()->current_select->olap == ROLLUP_TYPE) ||
 
1043
      (session->lex->select_lex.options & SELECT_BIG_RESULT) ||
 
1044
      (session->lex->current_select->olap == ROLLUP_TYPE) ||
1023
1045
      (select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) == OPTION_BIG_TABLES)
1024
1046
  {
1025
1047
    table->getMutableShare()->storage_engine= myisam_engine;
1450
1472
  return false;
1451
1473
}
1452
1474
 
1453
 
/**
1454
 
   True if the table's input and output record buffers are comparable using
1455
 
   compare_records(TABLE*).
1456
 
 */
1457
 
bool Table::records_are_comparable()
1458
 
{
1459
 
  return ((getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ) == 0) ||
1460
 
          write_set->is_subset_of(*read_set));
1461
 
}
1462
 
 
1463
 
/**
1464
 
   Compares the input and outbut record buffers of the table to see if a row
1465
 
   has changed. The algorithm iterates over updated columns and if they are
1466
 
   nullable compares NULL bits in the buffer before comparing actual
1467
 
   data. Special care must be taken to compare only the relevant NULL bits and
1468
 
   mask out all others as they may be undefined. The storage engine will not
1469
 
   and should not touch them.
1470
 
 
1471
 
   @param table The table to evaluate.
1472
 
 
1473
 
   @return true if row has changed.
1474
 
   @return false otherwise.
1475
 
*/
1476
 
bool Table::compare_records()
1477
 
{
1478
 
  if (getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ) != 0)
1479
 
  {
1480
 
    /*
1481
 
      Storage engine may not have read all columns of the record.  Fields
1482
 
      (including NULL bits) not in the write_set may not have been read and
1483
 
      can therefore not be compared.
1484
 
    */
1485
 
    for (Field **ptr= this->field ; *ptr != NULL; ptr++)
1486
 
    {
1487
 
      Field *f= *ptr;
1488
 
      if (write_set->test(f->position()))
1489
 
      {
1490
 
        if (f->real_maybe_null())
1491
 
        {
1492
 
          unsigned char null_byte_index= f->null_ptr - record[0];
1493
 
 
1494
 
          if (((record[0][null_byte_index]) & f->null_bit) !=
1495
 
              ((record[1][null_byte_index]) & f->null_bit))
1496
 
            return true;
1497
 
        }
1498
 
        if (f->cmp_binary_offset(getShare()->rec_buff_length))
1499
 
          return true;
1500
 
      }
1501
 
    }
1502
 
    return false;
1503
 
  }
1504
 
 
1505
 
  /*
1506
 
    The storage engine has read all columns, so it's safe to compare all bits
1507
 
    including those not in the write_set. This is cheaper than the
1508
 
    field-by-field comparison done above.
1509
 
  */
 
1475
/* Return false if row hasn't changed */
 
1476
 
 
1477
bool Table::compare_record()
 
1478
{
1510
1479
  if (not getShare()->blob_fields + getShare()->hasVariableWidth())
1511
 
    // Fixed-size record: do bitwise comparison of the records
1512
1480
    return memcmp(this->getInsertRecord(), this->getUpdateRecord(), (size_t) getShare()->getRecordLength());
1513
 
 
 
1481
  
1514
1482
  /* Compare null bits */
1515
1483
  if (memcmp(null_flags, null_flags + getShare()->rec_buff_length, getShare()->null_bytes))
1516
1484
    return true; /* Diff in NULL value */
1518
1486
  /* Compare updated fields */
1519
1487
  for (Field **ptr= field ; *ptr ; ptr++)
1520
1488
  {
1521
 
    if (isWriteSet((*ptr)->position()) &&
 
1489
    if (isWriteSet((*ptr)->field_index) &&
1522
1490
        (*ptr)->cmp_binary_offset(getShare()->rec_buff_length))
1523
1491
      return true;
1524
1492
  }
1625
1593
  query_id(0),
1626
1594
  quick_condition_rows(0),
1627
1595
  timestamp_field_type(TIMESTAMP_NO_AUTO_SET),
1628
 
  map(0),
1629
 
  quick_rows(),
1630
 
  const_key_parts(),
1631
 
  quick_key_parts(),
1632
 
  quick_n_ranges()
 
1596
  map(0)
1633
1597
{
1634
1598
  record[0]= (unsigned char *) 0;
1635
1599
  record[1]= (unsigned char *) 0;
 
1600
 
 
1601
  reginfo.reset();
 
1602
  covering_keys.reset();
 
1603
  quick_keys.reset();
 
1604
  merge_keys.reset();
 
1605
 
 
1606
  keys_in_use_for_query.reset();
 
1607
  keys_in_use_for_group_by.reset();
 
1608
  keys_in_use_for_order_by.reset();
 
1609
 
 
1610
  memset(quick_rows, 0, sizeof(ha_rows) * MAX_KEY);
 
1611
  memset(const_key_parts, 0, sizeof(ha_rows) * MAX_KEY);
 
1612
 
 
1613
  memset(quick_key_parts, 0, sizeof(unsigned int) * MAX_KEY);
 
1614
  memset(quick_n_ranges, 0, sizeof(unsigned int) * MAX_KEY);
1636
1615
}
1637
1616
 
1638
1617
/*****************************************************************************
1654
1633
    print them to the .err log
1655
1634
  */
1656
1635
  if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
1657
 
    errmsg_printf(error::ERROR, _("Got error %d when reading table '%s'"),
 
1636
    errmsg_printf(ERRMSG_LVL_ERROR, _("Got error %d when reading table '%s'"),
1658
1637
                  error, getShare()->getPath());
1659
1638
  print_error(error, MYF(0));
1660
1639
 
1732
1711
  }
1733
1712
}
1734
1713
 
1735
 
/*
1736
 
  Is this instance of the table should be reopen or represents a name-lock?
1737
 
*/
1738
 
bool Table::needs_reopen_or_name_lock() const
1739
 
1740
 
  return getShare()->getVersion() != refresh_version;
1741
 
}
1742
 
 
1743
 
uint32_t Table::index_flags(uint32_t idx) const
1744
 
{
1745
 
  return getShare()->getEngine()->index_flags(getShare()->getKeyInfo(idx).algorithm);
1746
 
}
1747
 
 
1748
 
void Table::print_error(int error, myf errflag) const
1749
 
{
1750
 
  getShare()->getEngine()->print_error(error, errflag, *this);
1751
 
}
1752
 
 
1753
1714
} /* namespace drizzled */