Problem/Motivation
With the $conf['dev_query'] = 1;specified in settings.php, the following errors are generated at the top of the page, logged in as admin user (non-user 1).
Notice: Trying to get property of non-object in includes/database.mysqli.inc on line 108
Notice: Trying to get property of non-object in includes/database.mysqli.inc on line 108
Warning: session_start(): Cannot send session cache limiter - headers already sent (output started at includes/database.mysqli.inc:108) in includes/bootstrap.inc on line 1172
Warning: Cannot modify header information - headers already sent by (output started at includes/database.mysqli.inc:108) in includes/bootstrap.inc on line 736
Warning: Cannot modify header information - headers already sent by (output started at includes/database.mysqli.inc:108) in includes/bootstrap.inc on line 737
Warning: Cannot modify header information - headers already sent by (output started at includes/database.mysqli.inc:108) in includes/bootstrap.inc on line 738
Warning: Cannot modify header information - headers already sent by (output started at includes/database.mysqli.inc:108) in includes/bootstrap.inc on line 739
The initial "trying to get property of non-object" error message appears twice because there are two queries that are executed before the session is created and the $user object is initialized. The reason is that drupal_is_denied() is invoked before $user is populated, which happens on the next bootstrap phase. ie. DRUPAL_BOOTSTRAP_ACCESS is executed before DRUPAL_BOOTSTRAP_SESSION.
I placed the following code snippet at the top of the _db_query() function:
if (!is_object($user)) {
print '<div>'. $query . '</div>';
}
It found that the following two queries are run before the $user global is initialized as an object:
SELECT 1 FROM access WHERE type = 'host' AND LOWER('127.0.0.1') LIKE LOWER(mask) AND status = 0 LIMIT 0, 1
SELECT u.*, s.* FROM users u INNER JOIN sessions s ON u.uid = s.uid WHERE s.sid = '12345678901234567890'
This problem only affects MySQL. PGSQL is not affected because database.pgsql.inc does not contain this query comment functionality as database.mysql.inc and database.mysqli.inc do
Proposed resolution
Wrap the $user->uid part of the if statement in a !empty().
Failing the !empty($user->uid) would imply that either the $user is not an object, or that the $user->uid is false or zero (in the case of anonymous) which is precisely what this code is testing for to use the $user->name inside the query comment functionality inside the _db_query() functions.
The attached patch fixes this for both mysql drivers. The pgsql driver is not affected.
Remaining tasks
Write patch.- Determine if D7 or D8 are affected.
- Review patch.
- Commit.
User interface changes
Some early database query calls (that may be displayed by devel module in onscreen logs) will show as 'Anonymous' instead of the current user's name in the query's comment.
API changes
None.
Data model changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #7 | core-mysql-dev-query-351844-7-D6.patch | 1.45 KB | jwilson3 |
| database.dev_query.patch | 1.4 KB | markus_petrux |
Comments
Comment #1
eileenmcnaughton commentedThis patch worked for me - although I applied against mysql.inc not mysqli.inc to make it work
Comment #3
pounardExperienced the same bug, because dev_query settings forces the _db_query() function to mess up with username, it will fail on every database access prior to session set.
In my case, having the dev_query settings in database is OK because variable_init() is called after the session stuff has been set. But as soon as I set the dev_query setting in the settings.php file, it crashed badly.
Comment #6
jwilson3I've marked an earlier issue as a duplicate of this one because this one has a patch:
#321089: Early bootstrap queries generate notices when query logging is enabled
FWIW, this issue has been reported no less than 4 times, here are the two others:
Comment #7
jwilson3The original test breaks when $user global is not yet defined as an object:
The patch from the OP adds this isset():
However, I believe just a !empty() around the $user->uid would be enough to catch when the item is not an object AND/OR the $user->uid is not an authenticated user.
Comment #8
jwilson3Comment #9
jwilson3Updated the issue title
Comment #10
jwilson3Comment #11
jwilson3Comment #12
jwilson3