"For MDEV-36290 (improved support of replication between tables of
different structure) I've addressed your review comments, as well as a
couple bugs found in test in the latest branch main-MDEV-36290. The
last 3 commits are incremental from the patch you reviewed. Do you
want to take a look?"

Here is the review for each patch in main-MDEV-36290

MDEV-36290: Address review comments (and some other cleanups found)

- Commit comment looks very good. Great that you addressed my concerns!

Relevant Comments from review script:

    // sql/rpl_utility_server.cc:1377
    -       continue;                               // ok that field
did not exists
    +       continue;                               // ok that field
did not exist

Rest of the suggestion where wrong

A funny note, I called review.sh accidentally with inverse argument so
the LLM thought your new code was the old code.

The main comments where:
*   **Good Architectural Change:** Moving the `write_set` update logic
into `unpack_row` is a clear improvement. It's more localized,
executed only when needed, and makes the data flow easier to
understand.
*   **Bug Fix:** The PR correctly identifies and resolves an assertion
failure (`marked_for_write_or_computed()`) when applying row events
with `NULL` values to fields that are not in the `write_set`. The
solution of temporarily marking the field for writing is appropriate.

After the above, the LLM got even more confused.
------
log_event_server.cc

-        if (ptr->create_column_mapping(rgi))
-        {
-          thd->is_slave_error= 1;
-          error= ERR_BAD_TABLE_DEF;
-          goto err;
-        }

ptr->create_column_mapping(rgi);

Note the create_column_mapping can fail if this fails:

m_tabledef.master_column_name[col]= (char *) alloc_root(
          rgi->thd->mem_root, field_name_sz * sizeof(char) + 1);

Better to keep the value as bool and do a goto err.
Error in thd is will automatically be set.
You can of course also set error ER_OUTOFMEMORY as the function returns error.

------
rpl_record.cc:

void prepare_null_field(Field *f)

Add #ifndef DBUG_OFF around

MY_BITMAP *write_set= f->table->write_set;

This is to avoid warnings about not used variables in not debug compilations.

An even better fix would be to add write_set as an argument to the macro
(I don't like macros that uses local variables in a hidden manner):

#define DBUG_FIX_WRITE_SET(f) bool _write_set_fixed=
!bitmap_fast_test_and_set(write_set, (f)->field_index)

->
#define DBUG_FIX_WRITE_SET(f,write_set) bool _write_set_fixed=
!bitmap_fast_test_and_set(write_set, (f)->field_index)

This way you don't need the write_set variable.

int unpack_row()

+  DBUG_ASSERT(!table->default_field || table->default_field[0]);
+  DBUG_ASSERT(!table->vfield || table->vfield[0]);
+
+  if (table->default_field && *(table->default_field) &&
+      (rpl_data.is_online_alter() ||
+       LOG_EVENT_IS_WRITE_ROW(rgi->current_event->get_type_code())))

You don't need to test for *(table->default_field) anymore.

-  if (table->vfield)
+  if (table->vfield && *(table->vfield))

Same here. Testing for table->vfield is enough.

-----

sql_table.cc:

  if (dfield_ptr)
-    *dfield_ptr= NULL;
+  {
+    if (dfield_ptr == to->default_field)
+      to->default_field= 0; // No default fields left
+    else
+      *dfield_ptr= NULL;
+  }

Add the following comments:

  if (dfield_ptr)
  {
     if (dfield_ptr == to->default_field)
       to->default_field= 0; // No default fields in table
    else
     *dfield_ptr= NULL;      // Mark end of default field pointers
  }


RPL_TABLE_LIST::create_column_mapping

    size_t field_name_sz= master_col_name_cppstr.size();
      m_tabledef.master_column_name[col]= (char *) alloc_root(
          rgi->thd->mem_root, field_name_sz * sizeof(char) + 1);
      strncpy(m_tabledef.master_column_name[col],
              master_col_name_cppstr.c_str(), field_name_sz);
      m_tabledef.master_column_name[col][field_name_sz] = '\0';

The above can be replace by:

m_tabledef.master_column_name[col]=
  rgi->thd->strmake(m_tabledef.master_column_name[col].ptr(),
                    m_tabledef.master_column_name[col].size());
if (!m_tabledef.master_column_name[col])
  return 1;  // Out of memory

It would also be nice if you could replace at some point std::string with
LEX_CSTRING, which is more efficent.  This also would allow us to get rid
if calling c_str() in a lot of places.
Note that find_field_by_name[] does not require string to be 0 terminated.

----
table.cc:

  if (dfield_ptr)
+  {
+    DBUG_ASSERT(table->default_field != dfield_ptr);
     *dfield_ptr= 0;
+  }

->

  if (dfield_ptr)
  {
    /* table->default_field == NULL if no default fields */
    DBUG_ASSERT(table->default_field != dfield_ptr);
    *dfield_ptr= 0;   // Mark end of default field pointers
  }

--------------------

commit cfe91d97c82221a42eb1b1e26ec168a9a8a1ec1c
Author: Brandon Nesterenko <[email protected]>
Date:   Fri Oct 10 12:53:44 2025 -0600

    MDEV-37737: SIGABRT upon executing BINLOG statement

ok

commit 16c8bcc09a22709fdb770ee267317dac1e033984 (HEAD ->
main-MDEV-36290, origin/main-MDEV-36290)
Author: Brandon Nesterenko <[email protected]>
Date:   Fri Oct 10 13:09:07 2025 -0600

    MDEV-37836: ASAN: global-buffer-overflow in
Sys_var_typelib::Sys_var_typelib on MDEV-36290 branch on server
startup

ok
-----

Regards,
Monty
_______________________________________________
commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to