3

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.

1
  • I luckily chanced upon this SO question via a Google search and logged in to up vote because this seems to be my exact same problem. But SO won't let me upvote the question... Turns out this is my question, which I wrote 6 months ago. :P
    – rinogo
    Commented Nov 3, 2014 at 18:14

2 Answers 2

1

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)

1
  • Note that while this works, it only solves part of the problem. Once I implemented this core hack, another similar issue cropped up in Wordpress' blog setup code. Once I fixed that, another one cropped up. I wonder how deep this rabbit hole goes... Perhaps I can revisit this later...
    – rinogo
    Commented Nov 3, 2014 at 20:16
0

DB errors of that type should only appear on the UI if DB_DEBUG is enabled. On a production system that should be disabled. You should find that setting in the wp-config.php file for your WP install.

You can try to manually force the errors to "hide" by resetting the EZSQL_ERROR global. This is my personal hack and probably not recommended or best practice for working with dbDelta:

/**
 * Update the data structures on new db versions.
 *
 * @global object $wpdb
 * @param type $sql
 * @param type $table_name
 * @return string
 */
function dbupdater($sql,$table_name) {
    global $wpdb;
    $retval = ( $wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name ) ? 'new' : 'updated';

    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    $were_showing_errors = $wpdb->show_errors;
    $wpdb->hide_errors();
    dbDelta($sql);
    global $EZSQL_ERROR;
    $EZSQL_ERROR=array();
    if ( $were_showing_errors ) {
        $wpdb->show_errors();
    }

    return $retval;
}
3
  • Thanks for your answer! Unfortunately, the issue isn't related to errors showing or not showing. Rather, the issue is that Wordpress is not catching the related database error (regardless of whether or not it is displayed to the end user). Put succinctly, Wordpress is generating errors that appear in our error log that are not really true errors. They are (I assume), side-effects of a correctly functioning dbDelta() function. This causes our reporting systems to inaccurately conclude that there are issues with our production environment, since it is consistently generating errors.
    – rinogo
    Commented Apr 21, 2014 at 22:31
  • 1
    Good point. Part of the issue is the construct of using DESCRIBE {table} when table does not exist. Before executing the DESCRIBE SQL statement the MySQL engine should be queried to see if the table exists in the first place. The issue is not that a warning/error is not being caught it is that the construct is generating a warning/error in the first place. Commented Apr 22, 2014 at 16:58
  • Either way, sounds like a patch might be in order! :P
    – rinogo
    Commented Apr 22, 2014 at 18:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.