There is a problem with the return value description for mysqli_query. Under Return Values, it says:

Returns false on failure. For successful SELECT, SHOW, DESCRIBE or EXPLAIN queries mysqli_query() will return a mysqli_result object. For other successful queries mysqli_query() will return true

This is not correct. I can provide one counterexample, which is when you run an optimize query:

if ($result = $mysqli->query("OPTIMIZE TABLE db_job")) {

    /* determine number of rows result set */
    $row_cnt = $result->num_rows;
    printf("Result set has %d rows.\n", $row_cnt);

    while($row = $result->fetch_array()) {
        var_dump($row);
    }

    /* close result set */
    $result->close();
}

This query will return a result set with two records whether the table exists or not. If the table exists:

array(8) {
  [0]=>
  string(15) "ci4_test.db_job"
  ["Table"]=>
  string(15) "ci4_test.db_job"
  [1]=>
  string(8) "optimize"
  ["Op"]=>
  string(8) "optimize"
  [2]=>
  string(4) "note"
  ["Msg_type"]=>
  string(4) "note"
  [3]=>
  string(65) "Table does not support optimize, doing recreate + analyze instead"
  ["Msg_text"]=>
  string(65) "Table does not support optimize, doing recreate + analyze instead"
}
array(8) {
  [0]=>
  string(15) "ci4_test.db_job"
  ["Table"]=>
  string(15) "ci4_test.db_job"
  [1]=>
  string(8) "optimize"
  ["Op"]=>
  string(8) "optimize"
  [2]=>
  string(6) "status"
  ["Msg_type"]=>
  string(6) "status"
  [3]=>
  string(2) "OK"
  ["Msg_text"]=>
  string(2) "OK"
}

If the table does not exist:

array(8) {
  [0]=>
  string(29) "ci4_test.table_does_not_exist"
  ["Table"]=>
  string(29) "ci4_test.table_does_not_exist"
  [1]=>
  string(8) "optimize"
  ["Op"]=>
  string(8) "optimize"
  [2]=>
  string(5) "Error"
  ["Msg_type"]=>
  string(5) "Error"
  [3]=>
  string(51) "Table 'ci4_test.table_does_not_exist' doesn't exist"
  ["Msg_text"]=>
  string(51) "Table 'ci4_test.table_does_not_exist' doesn't exist"
}
array(8) {
  [0]=>
  string(29) "ci4_test.table_does_not_exist"
  ["Table"]=>
  string(29) "ci4_test.table_does_not_exist"
  [1]=>
  string(8) "optimize"
  ["Op"]=>
  string(8) "optimize"
  [2]=>
  string(6) "status"
  ["Msg_type"]=>
  string(6) "status"
  [3]=>
  string(16) "Operation failed"
  ["Msg_text"]=>
  string(16) "Operation failed"
}

I sent an email to phpdoc mailing lists (at lists dot php dot net) and someone responded:

The documentation is correct (at least that part) but what you have encountered is a bug, either in mysqli or in MySQL. Please file a bug report on https://bugs.php.net/ and we will look into it.

Is this documentation problem or bug? Shoudl I report it to bugs.php.net regardless?

    There is some confusion about what return values are, especially in cases where there is both a procedural and an object-oriented interface. See https://bugs.php.net/bug.php?id=80529 for another recent example.

    The return value applies to the procedural invocation; OO invocations always return a MySQLi object (or throw I guess, but then what would errno be for?); but what that object contains isn't necessarily clear.

    It depends on what OPTIMIZE results in; if it returns a result set reporting the outcome of the operation then there's probably nothing on PHP's side that could know that it represents anything other than a set of results (being itself blind to SQL and MySQL's particular dialect).

    Since table optimisation (and indeed indexing in general) is beyond the scope of standard SQL, there's probably no SQL error code to represent their failure. (On the other hand, SQLSTATE 42S02 means "table does not exist"; MySQL's developers seemed to have made the choice that not finding a table does not count as an error in this situation.)

      Write a Reply...