2
2
3
3
namespace Barryvdh \Debugbar \Support ;
4
4
5
- use DB ;
6
5
use Exception ;
7
6
use Illuminate \Database \ConnectionInterface ;
7
+ use Illuminate \Database \QueryException ;
8
+ use Illuminate \Support \Facades \DB ;
8
9
use Illuminate \Support \Facades \Http ;
9
10
10
11
class Explain
11
12
{
12
- public function confirm (string $ connection ): ?string
13
+ public function isVisualExplainSupported (string $ connection ): bool
14
+ {
15
+ $ driver = DB ::connection ($ connection )->getDriverName ();
16
+ if ($ driver === 'pgsql ' ) {
17
+ return true ;
18
+ }
19
+ if ($ driver === 'mysql ' ) {
20
+ // Laravel 11 added a new MariaDB database driver but older Laravel versions handle MySQL and MariaDB with
21
+ // the same driver - and even with new versions you can use the MySQL driver while connection to a MariaDB
22
+ // database. This query uses a feature implemented only in MariaDB to differentiate them.
23
+ try {
24
+ DB ::connection ($ connection )->select ('SELECT * FROM seq_1_to_1 ' );
25
+
26
+ return false ;
27
+ } catch (QueryException ) {
28
+ // This exception is expected when using MySQL as sequence tables are only available with MariaDB. So
29
+ // the exception gets silenced as the check for MySQL has succeeded.
30
+ return true ;
31
+ }
32
+ }
33
+
34
+ return false ;
35
+ }
36
+
37
+ public function confirmVisualExplain (string $ connection ): ?string
13
38
{
14
39
return match (DB ::connection ($ connection )->getDriverName ()) {
15
40
'mysql ' => 'The query and EXPLAIN output is sent to mysqlexplain.com. Do you want to continue? ' ,
@@ -23,7 +48,7 @@ public function hash(string $connection, string $sql, array $bindings): string
23
48
$ bindings = json_encode ($ bindings );
24
49
25
50
return match (DB ::connection ($ connection )->getDriverName ()) {
26
- 'mysql ' , 'pgsql ' => hash_hmac ('sha256 ' , "{$ connection }:: {$ sql }:: {$ bindings }" , config ('app.key ' )),
51
+ 'mariadb ' , ' mysql ' , 'pgsql ' => hash_hmac ('sha256 ' , "{$ connection }:: {$ sql }:: {$ bindings }" , config ('app.key ' )),
27
52
default => null ,
28
53
};
29
54
}
@@ -42,7 +67,7 @@ public function generateRawExplain(string $connection, string $sql, array $bindi
42
67
$ connection = DB ::connection ($ connection );
43
68
44
69
return match ($ driver = $ connection ->getDriverName ()) {
45
- 'mysql ' => $ connection ->select ("EXPLAIN {$ sql }" , $ bindings ),
70
+ 'mariadb ' , ' mysql ' => $ connection ->select ("EXPLAIN {$ sql }" , $ bindings ),
46
71
'pgsql ' => array_column ($ connection ->select ("EXPLAIN {$ sql }" , $ bindings ), 'QUERY PLAN ' ),
47
72
default => throw new Exception ("Visual explain not available for driver ' {$ driver }'. " ),
48
73
};
@@ -51,13 +76,15 @@ public function generateRawExplain(string $connection, string $sql, array $bindi
51
76
public function generateVisualExplain (string $ connection , string $ sql , array $ bindings , string $ hash ): string
52
77
{
53
78
$ this ->verify ($ connection , $ sql , $ bindings , $ hash );
79
+ if (!$ this ->isVisualExplainSupported ($ connection )) {
80
+ throw new Exception ('Visual explain not available for this connection. ' );
81
+ }
54
82
55
83
$ connection = DB ::connection ($ connection );
56
84
57
- return match ($ driver = $ connection ->getDriverName ()) {
85
+ return match ($ connection ->getDriverName ()) {
58
86
'mysql ' => $ this ->generateVisualExplainMysql ($ connection , $ sql , $ bindings ),
59
87
'pgsql ' => $ this ->generateVisualExplainPgsql ($ connection , $ sql , $ bindings ),
60
- default => throw new Exception ("Visual explain not available for driver ' {$ driver }'. " ),
61
88
};
62
89
}
63
90
@@ -70,7 +97,7 @@ private function generateVisualExplainMysql(ConnectionInterface $connection, str
70
97
'bindings ' => $ bindings ,
71
98
'version ' => $ connection ->selectOne ("SELECT VERSION() " )->{'VERSION() ' },
72
99
'explain_json ' => $ connection ->selectOne ("EXPLAIN FORMAT=JSON {$ query }" , $ bindings )->EXPLAIN ,
73
- 'explain_tree ' => rescue (fn () => $ connection ->selectOne ("EXPLAIN FORMAT=TREE {$ query }" , $ bindings ), report: false )-> EXPLAIN ,
100
+ 'explain_tree ' => rescue (fn () => $ connection ->selectOne ("EXPLAIN FORMAT=TREE {$ query }" , $ bindings )-> EXPLAIN , report: false ),
74
101
])->throw ()->json ('url ' );
75
102
}
76
103
0 commit comments