Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-6624

Updating or deleteting on a CONNECT void table produces "unknown error"

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 10.0.13
    • Fix Version/s: 10.0.14
    • Component/s: None
    • Labels:
      None

      Description

      When trying to do:

      update tstx set msg = 'bof' where id = 35;
      

      on the table:

      create table tstx (
      id int(4) key not null,
      msg varchar(16))
      engine=connect table_type=FIX  block_size=4;
      

      in which no rows have been inserted yet or all rows deleted, results in the message:

       
      Got error 122 "Internal (unspecified) error in handler"
      

      This occurs despite the handler does not return any error code (it just pushes a warning)

      It seems that this occurs in mysql_update in sql_update.cc line 910:

        /*
          Caching the killed status to pass as the arg to query event constuctor;
          The cached value can not change whereas the killed status can
          (externally) since this point and change of the latter won't affect
          binlogging.
          It's assumed that if an error was set in combination with an effective 
          killed status then the error is due to killing.
        */
        killed_status= thd->killed; // get the status of the volatile 
        // simulated killing after the loop must be ineffective for binlogging
        DBUG_EXECUTE_IF("simulate_kill_bug27571",
                        {
                          thd->killed= KILL_QUERY;
                        };);
        error= (killed_status == NOT_KILLED)?  error : 1;
      

      I haven't the faintest idea of what this code does but in normal cases the error variable remains equal to -1 while in this case it is set to 122 causing the error.

        Gliffy Diagrams

          Attachments

            Activity

            Hide
            serg Sergei Golubchik added a comment - - edited

            See the last line

             error= (killed_status == NOT_KILLED)?  error : 1;
            

            as you can see, it sets the error to 1 if the query execution was killed, otherwise it keeps the old error value.
            It is 122 (HA_ERR_INTERNAL_ERROR) because in ha_connect::index_read() you return HA_ERR_INTERNAL_ERROR when a key is not found:

              } else
                rc= HA_ERR_INTERNAL_ERROR;  // HA_ERR_KEY_NOT_FOUND ?
            
              DBUG_RETURN(rc);
            } // end of index_read
            

            I'm not sure why you think that a not found key is an internal error, it can easily happen on, for example,

            SELECT * FROM table WHERE key_column='nonexistent_value';
            

            If I change the returned error code to HA_ERR_KEY_NOT_FOUND, then your test case works correctly.

            Show
            serg Sergei Golubchik added a comment - - edited See the last line error= (killed_status == NOT_KILLED)? error : 1; as you can see, it sets the error to 1 if the query execution was killed, otherwise it keeps the old error value. It is 122 (HA_ERR_INTERNAL_ERROR) because in ha_connect::index_read() you return HA_ERR_INTERNAL_ERROR when a key is not found: } else rc= HA_ERR_INTERNAL_ERROR; // HA_ERR_KEY_NOT_FOUND ? DBUG_RETURN(rc); } // end of index_read I'm not sure why you think that a not found key is an internal error, it can easily happen on, for example, SELECT * FROM table WHERE key_column='nonexistent_value'; If I change the returned error code to HA_ERR_KEY_NOT_FOUND , then your test case works correctly.
            Hide
            serg Sergei Golubchik added a comment -

            I did that change, all tests passed. I'm going to push it, unless you disagree.

            Show
            serg Sergei Golubchik added a comment - I did that change, all tests passed. I'm going to push it, unless you disagree.
            Hide
            bertrandop Olivier Bertrand added a comment - - edited

            This did mask the error by chance but it is not the real cause. It is more complex:

            In index_read I normally call ReadIndexed that returns HA_ERR_KEY_NOT_FOUND n this case.
            What happened here comes from index_init in which for a void table I wrongly return 0 without setting active_index = MAX_KEY but setting my internal indexing variable to 0 meaning no index use.
            In this case this caused index_read to be called when I expect no indexing to be used. This is why I return HA_ERR_INTERNAL_ERROR.
            Of course, here no more error message from MariaDB but the fix should not be here but in index_init.
            I will look at it and make a proper fix.

            Thanks for showing me where the problem comes from.

            Show
            bertrandop Olivier Bertrand added a comment - - edited This did mask the error by chance but it is not the real cause. It is more complex: In index_read I normally call ReadIndexed that returns HA_ERR_KEY_NOT_FOUND n this case. What happened here comes from index_init in which for a void table I wrongly return 0 without setting active_index = MAX_KEY but setting my internal indexing variable to 0 meaning no index use. In this case this caused index_read to be called when I expect no indexing to be used. This is why I return HA_ERR_INTERNAL_ERROR. Of course, here no more error message from MariaDB but the fix should not be here but in index_init. I will look at it and make a proper fix. Thanks for showing me where the problem comes from.
            Hide
            bertrandop Olivier Bertrand added a comment - - edited

            The fix I have done is to accept the indexing which of course returns record not found in index_read.

            However, it is not quite what I wished to do because it seems that there is no way to tell MariaDB not to use indexing at all. Setting active_index to MAX_KEY does not work because when returning 0 it is set to idx in the calling function and returning an error value cause an error to be raised.

            I already met this problem and it would be nice to be able to do it, mainly because the SQL syntax does not allow ignoring indexes for not select statement.

            Show
            bertrandop Olivier Bertrand added a comment - - edited The fix I have done is to accept the indexing which of course returns record not found in index_read. However, it is not quite what I wished to do because it seems that there is no way to tell MariaDB not to use indexing at all. Setting active_index to MAX_KEY does not work because when returning 0 it is set to idx in the calling function and returning an error value cause an error to be raised. I already met this problem and it would be nice to be able to do it, mainly because the SQL syntax does not allow ignoring indexes for not select statement.
            Hide
            serg Sergei Golubchik added a comment -

            Okay, great. I will revert my fix then (it wasn't pushed yet). Thanks!

            Show
            serg Sergei Golubchik added a comment - Okay, great. I will revert my fix then (it wasn't pushed yet). Thanks!

              People

              • Assignee:
                bertrandop Olivier Bertrand
                Reporter:
                bertrandop Olivier Bertrand
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:

                  Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0 minutes
                  0m
                  Logged:
                  Time Spent - 1 hour, 15 minutes
                  1h 15m