Brian "Krow" Aker (krow) wrote,
Brian "Krow" Aker
krow

Building a Storage Engine: Updating Data

In our last installment, we looked at how to write data into a storage engine, now lets look at updating it.

To update data you need to first know that it exists. To do this MySQL reads the rows that need to be updated, either by index or scan read. Since we have already spoken on scan reads, we are going to look at updates that occur that need to scan the entire table. MySQL will start up a read and do the folllowing:

rnd_init()
rnd_next()
rnd_next()
rnd_next()
update_row()
rnd_next()
rnd_next()
rnd_end()

In the above example, MySQL find four rows in the table. The third row is matched for an update. The engine writer doesn't have to do to the predicate test themselves (aka ... UPDAT E A SET b=5 WHERE a=3, the engine writer doesn't need to worry about matching the a=3). The update_row() code looks like this:

int ha_skeleton::update_row(const byte * old_data, byte * new_data)
{
   DBUG_ENTER("ha_skeleton::update_row");
   char content_buffer[1024];
   String content(content_buffer, sizeof(content_buffer),
                    &my_charset_bin);
   char utf8_buffer[1024];
   String utf8(utf8_buffer, sizeof(utf8_buffer),
                    &my_charset_bin);
   utf8.length(0);
   content.length(0);

   ha_statistic_increment(&SSV::ha_read_rnd_next_count);

   if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
     table->timestamp_field->set_time();


   for (Field **field=table->field ; *field ; field++)
   {
     if ((*field)->is_null())
     {
       xml_engine_row_add(engine_clone, (char *)(*field)->field_name, NULL, 0, 1);
     }
     else
     {
       (*field)->val_str(&content);
       utf8.set(content->ptr(), content->length(), content->charset(),
                &my_charset_utf8_general_ci, &error_count);

       xml_engine_row_add(engine_clone, (char *)(*field)->field_name,
                          content.c_ptr_safe(), content.length(), 1);
     }
   }
   xml_engine_update(engine_clone);

   DBUG_RETURN(0);
}



The two arguments passed into update_row is the old image, and the new image of the row. The Field objects points to the data in old row. We loop through the new row and push the data into the storage engine. Notice that we differentiate between NULL and no content. While some engines in MySQL don't store NULL as NULL in MySQL, CSV for example, almost all engines store NULL.

Notice that there is no update_end() call. If you require this sort of call it is best to flag that an update occurred and then use the index_end() or rnd_end() methods to do any cleanup required.

Since the xml database only operates in UTF8, notice that we used the internal mysql String class to convert the content to UTF8 before storage. You can use this to convert character sets MySQL supports.

You can find the code for this in Chapter 4 of:
http://hg.tangent.org/writing_engines_for_mysql

Previous articles in this series:
The previous entries in this series:
Getting The Skeleton to Compile
Reading Data
Writing Data
Subscribe
  • Post a new comment

    Error

    Comments allowed for friends only

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments