Commit 5d3af2b0 authored by unknown's avatar unknown
Browse files

WL 1682: Use bitvector instead of query_id to tell handler which fields

to read and write
Changed Server code, added new interface to handler and changed the
NDB handler, InnoDB handler and Federated handler that previously used
query_id
Bug#10202 fix (one-liner fix for memory leak)


mysys/my_bitmap.c:
  Debug code
sql/field.cc:
  Initialise fieldnr to 0 if not set anywhere else
sql/field.h:
  Introduce a fieldnr (first field = 1 and last = table->s->fields
  in field object to be able to quickly set appropriate bit in
  read/write set
sql/ha_federated.cc:
  Changed federated handler to use write set instead of query_id
sql/ha_innodb.cc:
  Changed InnoDB handler to use write set instead of query_id
sql/ha_ndbcluster.cc:
  Changed NDB handler to use write set instead of query_id
sql/ha_ndbcluster.h:
  Changed NDB handler to use write set instead of query_id
sql/handler.cc:
  Allocate read_set and write_set either in get_new_handler or in
  special routine
  Routines used at destruction of handler object
  plus routine to set all primary key fields in read_set
sql/handler.h:
  bool to keep track if read/write set allocated or not in handler
  Deallocate read/write set at delete of handler object
  New bitmap's for read/write set
sql/item.cc:
  Set bits in read or write set (set_query_id = 2 => write_set
  set_query_id = 1 => read_set
sql/lock.cc:
  Clear bit set when starting a new statement in external lock
sql/mysql_priv.h:
  changed set_query_id from bool to ulong
sql/opt_range.cc:
  Set primary key read set in all places where HA_EXTRA_RETRIEVE_PRIMARY_KEY
  is used
sql/sql_acl.cc:
  set all bits in read set all places where HA_EXTRA_RETRIEVE_ALL_COLS
  are used
sql/sql_base.cc:
  Clear all bits before start new statement when table locked already
  Set bit in read/write set dependent on set_query_id and fieldnr
  bool -> ulong for set_query_id
  set all bits in read set for SELECT * queries where table is not view
sql/sql_class.h:
  Added comments + changed type of set_query_id
sql/sql_insert.cc:
  Use 2 when setup_fields called for fields to updated in UPDATE
  and INSERT statements
  set primary key fields when EXTRA param used
sql/sql_load.cc:
  Set all bits in write set if no fields specified in LOAD DATA FROM
  INFILE
  Otherwise use 2 to set specific fields to be updated by LOAD DATA...
sql/sql_select.cc:
  Set primary key read set when EXTRA param specified
  Set fieldnr for temporary tables
  Set number of fields before calling get_new_handler
  and only set all bits if there at least one field in table
sql/sql_table.cc:
  Set all bits in read set for old table and all bits in write set for
  new table for ALTER TABLE copy method
  Set all bits in read set when EXTRA param used
sql/sql_udf.cc:
  Set all bits in read set when EXTRA param used
sql/sql_update.cc:
  Set fields to UPDATE to use 2 for set_query_id
  Set all bits in read set when EXTRA param used
sql/table.cc:
  Set fieldnr in openfrm
  Reallocate read/write set in openfrm since table->s->fields==0
  at call to get_new_handler
sql/unireg.cc:
  Fix Bug #10202
parent a2ed27af
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -102,6 +102,14 @@ void bitmap_free(MY_BITMAP *map)

void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit)
{
  if (map->bitmap)
  {
    DBUG_PRINT("info", ("Bitmap not defined"));
  }
  if (bitmap_bit >= map->bitmap_size*8)
  {
    DBUG_PRINT("info", ("bit %d size in bytes %d", bitmap_bit, map->bitmap_size));
  }
  DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
  bitmap_lock(map);
  bitmap_fast_set_bit(map, bitmap_bit);
+1 −0
Original line number Diff line number Diff line
@@ -1198,6 +1198,7 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
  flags=null_ptr ? 0: NOT_NULL_FLAG;
  comment.str= (char*) "";
  comment.length=0;
  fieldnr= 0;
}

uint Field::offset()
+1 −0
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@ class Field
  utype		unireg_check;
  uint32	field_length;		// Length of field
  uint16	flags;
  uint16        fieldnr;                // Field number
  uchar		null_bit;		// Bit used to test null bit

  Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,uchar null_bit_arg,
+6 −36
Original line number Diff line number Diff line
@@ -1076,11 +1076,8 @@ inline uint field_in_record_is_null(TABLE *table,

int ha_federated::write_row(byte *buf)
{
  uint x= 0, num_fields= 0;
  uint x, num_fields;
  Field **field;
  ulong current_query_id= 1;
  ulong tmp_query_id= 1;
  uint all_fields_have_same_query_id= 1;

  char insert_buffer[IO_SIZE];
  char values_buffer[IO_SIZE], insert_field_value_buffer[IO_SIZE];
@@ -1105,14 +1102,6 @@ int ha_federated::write_row(byte *buf)
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
    table->timestamp_field->set_time();

  /*
    get the current query id - the fields that we add to the insert
    statement to send to the foreign will not be appended unless they match
    this query id
  */
  current_query_id= table->in_use->query_id;
  DBUG_PRINT("info", ("current query id %d", current_query_id));

  /* start off our string */
  insert_string.append("INSERT INTO `");
  insert_string.append(share->table_base_name);
@@ -1120,44 +1109,25 @@ int ha_federated::write_row(byte *buf)
  /* start both our field and field values strings */
  insert_string.append(" (");
  values_string.append(" VALUES (");

  /*
    Even if one field is different, all_fields_same_query_id can't remain
    0 if it remains 0, then that means no fields were specified in the query
    such as in the case of INSERT INTO table VALUES (val1, val2, valN)
  */
  for (field= table->field; *field; field++, x++)
  {
    if (x > 0 && tmp_query_id != (*field)->query_id)
      all_fields_have_same_query_id= 0;

    tmp_query_id= (*field)->query_id;
  }
  /*
    loop through the field pointer array, add any fields to both the values
    list and the fields list that match the current query id
    list and the fields list that is part of the write set
  */
  x=0;
  for (field= table->field; *field; field++, x++)
  for (x=0, num_fields= 0, field= table->field; *field; field++, x++)
  {
    /* if there is a query id and if it's equal to the current query id */
    if (((*field)->query_id && (*field)->query_id == current_query_id)
        || all_fields_have_same_query_id)
    if (ha_get_bit_in_write_set((*field)->fieldnr))
    {
      num_fields++;

      if ((*field)->is_null())
      {
        DBUG_PRINT("info",
                   ("column %d current query id %d field is_null query id %d",
                    x, current_query_id, (*field)->query_id));
        DBUG_PRINT("info", ("column %d field is_null", x));
        insert_field_value_string.append("NULL");
      }
      else
      {
        DBUG_PRINT("info",
                   ("column %d current query id %d field is not null query ID %d",
                    x, current_query_id, (*field)->query_id));
        DBUG_PRINT("info", ("column %d field is not null", x));
        (*field)->val_str(&insert_field_value_string);
        /* quote these fields if they require it */
        (*field)->quote_data(&insert_field_value_string); }
+2 −1
Original line number Diff line number Diff line
@@ -2684,7 +2684,8 @@ build_template(
		     (!(fetch_all_in_key && index_contains_field) &&
		      !(fetch_primary_key_cols &&
			dict_table_col_in_clustered_key(index->table, i)) &&
		      thd->query_id != field->query_id))) {
                      !(ha_get_bit_in_read_set(i+1) ||
                        ha_get_bit_in_write_set(i+1))))) {

			/* This field is not needed in the query, skip it */

Loading