From what I can see, dbDelta() is designed to suppress database errors that occur during its operation. Generally speaking, this seems to be the case, but New Relic is still reporting MysqlErrors from the function. The exact error message is of the format:

MysqlError: Table 'xxx.wp_yyy_posts' doesn't exist

From dbDelta() in /wp-admin/includes/upgrade.php, we have:

// Fetch the table column structure from the database
$suppress = $wpdb->suppress_errors();
$tablefields = $wpdb->get_results("DESCRIBE {$table};");
$wpdb->suppress_errors( $suppress );

It appears that suppress_errors() is doing it’s job and preventing error messages from being echoed to the screen. However, it also appears that these errors are not actually being handled, as shown by our New Relic installation.

Understandably, we would like to eliminate all possible sources of errors on our production app so that we can accurately use the New Relic tool for tracking actual error rates and associate them with New Relic’s reporting tools.

Is there a compelling reason why dbDelta() doesn’t handle this error? The only reason I can think of is that this is a deliberate design decision to facilitate development and bug-fixing. It could be hard for a developer to track down issues when dbDelta() completely suppresses any errors. Of course, a new parameter/option could be introduced to specify whether or not this automatic error suppression should occur (which would make catching the MysqlError a no-brainer).

This becomes a bit of an issue in our case in which every single call to install_blog() generates this error. Since we are running a large multisite installation, every time we create a new blog, an error is generated.

2 Answers
2

As @Charleston Software Associates mentioned, the DESCRIBE query should not be executed if the table doesn’t exist. The best solution, as he pointed out, is to prevent the error from occurring in the first place.

To do so, patch wp-admin/includes/upgrade.php as follows:

Change the following line from dbDelta():

  $tablefields = $wpdb->get_results("DESCRIBE {$table};”);

to:

    //Begin core hack - See http://wordpress.stackexchange.com/q/141971/10388
    $check_table = $wpdb->get_results("SHOW TABLES LIKE '".str_replace("_", "\_", $table)."';");
    if(!empty($check_table))
        $tablefields = $wpdb->get_results("DESCRIBE {$table};");
    else
        $tablefields = null;
    //End core hack

This isn’t the cleanest solution (especially since it’s a core hack), but it works for me, at least! Perhaps it will help someone else.

UPDATE: See my comment below. (This doesn’t fully resolve the problem, although it is a step in the right direction)

Leave a Reply

Your email address will not be published. Required fields are marked *