-
Notifications
You must be signed in to change notification settings - Fork 11.7k
Capture PDO read / write type for query events #58156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 12.x
Are you sure you want to change the base?
Conversation
|
Thanks for submitting a PR! Note that draft PR's are not reviewed. If you would like a review, please mark your pull request as ready for review in the GitHub user interface. Pull requests that are abandoned in draft may be closed due to inactivity. |
| public function __construct($sql, $bindings, $time, $connection) | ||
| public function __construct($sql, $bindings, $time, $connection, $readWriteType = null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Constructor remains backwards compatible.
|
cc @avosalmon 👀 |
| */ | ||
| protected function latestPdoTypeUsed() | ||
| { | ||
| return $this->readWriteType ?? $this->latestPdoTypeUsed; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this always return $this->latestPdoTypeUsed if we want to know the actual PDO that was used to run the query?
$this->readWriteType does not tell the real read/write type that was actually used.
If you run the following query, it sets the readWriteType to write, but it still uses the read connection as it's a select query.
DB::connection('pgsql::write')->table('users')->count();There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@avosalmon, when using the explicit ::write or ::read connection, although both the read and write PDO properties are populated, they contain the same PDO instance once both resolved, for example:
// file: config/database.php
'connections' => [
'sqlite' => [
// ...
'write' => [
'database' => env('DB_DATABASE', database_path('database.write.sqlite')),
],
'read' => [
'database' => env('DB_DATABASE', database_path('database.read.sqlite')),
],
// ...
],Artisan::command('dev', function () {
DB::connection('sqlite')->select('select 1');
DB::connection('sqlite')->statement('select 1');
dump(DB::connection('sqlite')->getRawReadPdo() === DB::connection('sqlite')->getRawPdo());
DB::connection('sqlite::read')->select('select 1');
DB::connection('sqlite::read')->statement('select 1');
dump(DB::connection('sqlite::read')->getRawReadPdo() === DB::connection('sqlite::read')->getRawPdo());
DB::connection('sqlite::write')->select('select 1');
DB::connection('sqlite::write')->statement('select 1');
dump(DB::connection('sqlite::write')->getRawReadPdo() === DB::connection('sqlite::write')->getRawPdo());
});
If we don't respect the readWriteType value, then it could incorrectly say you are using the write PDO when you are using the read PDO. Keep in mind that we are talking about the actual configured PDO regardless of what property it is attached to.
In your example, DB::connection('pgsql::write')->table('users')->count(); is using the configured write connection, which is what we care about as a consumer of the read / write type.
d3e3cda to
ce55981
Compare
This PR exposes the read / write type to the query executed event and query exceptions for better debugging and logging.
I've found there isn't a bulletproof way to determine this with what Laravel already exposes. You can get it right in 95% of cases, but there are certain scenarios where it is impossible to know for sure if a query was against the read or write connection.
This method of tracking the last resolved PDO, although feeling a little weird, is the best way I can see of making this correct in all cases.