Skip to content

Commit

Permalink
feat: support new v2 api
Browse files Browse the repository at this point in the history
  • Loading branch information
tpetry committed Jul 11, 2024
1 parent a6a88b4 commit 218a444
Show file tree
Hide file tree
Showing 8 changed files with 8 additions and 89 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Three new methods have been added to the query builder for very easy submission


```php
// $url will be e.g. https://mysqlexplain.com/e/C0Omak70mLEXfok1a7Oo1n
// $url will be e.g. https://mysqlexplain.com/explain/01j2gcrbsjet9r8rav114vgfsy
$url = Film::where('description', 'like', '%astronaut%')
->explainForHumans();

Expand All @@ -45,8 +45,7 @@ $users = Film::where('description', 'like', '%astronaut%')

// URL to EXPLAIN will be printed to screen & execution is stopped
$users = Film::where('description', 'like', '%astronaut%')
->ddExplainForHumans()
->get();
->ddExplainForHumans();
```

### Raw Queries
Expand All @@ -56,7 +55,7 @@ In some cases you are executing raw SQL queries and don't use the query builder.
```php
use Tpetry\MysqlExplain\Facades\MysqlExplain;

// $url will be e.g. https://mysqlexplain.com/e/H1pfKQ7FH3HnH87dS64Wk1
// $url will be e.g. https://mysqlexplain.com/explain/01j2gctgtheyva7a7mhpv8azje
$url = MysqlExplain::submitQuery(
DB::connection('mysql'),
'SELECT * FROM actor WHERE first_name = ?',
Expand Down
10 changes: 0 additions & 10 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,3 @@ parameters:
message: "#^Parameter \\$version of class Tpetry\\\\MysqlExplain\\\\Values\\\\QueryMetrics constructor expects string, float\\|int\\|string\\|null given\\.$#"
count: 1
path: src/MysqlExplain.php

-
message: "#^Property Tpetry\\\\MysqlExplain\\\\Values\\\\QueryMetrics\\:\\:\\$explainTraditional type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Values/QueryMetrics.php

-
message: "#^Property Tpetry\\\\MysqlExplain\\\\Values\\\\QueryMetrics\\:\\:\\$warnings type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Values/QueryMetrics.php
6 changes: 2 additions & 4 deletions src/Helpers/ApiHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ApiHelper
private Client $client;

public function __construct(
private ?string $domain = 'https://mysqlexplain.com',
private ?string $domain = 'https://api.mysqlexplain.com',
?Client $client = null,
) {
$this->client = $client ?? new Client();
Expand All @@ -29,18 +29,16 @@ public function submitPlan(QueryMetrics $metrics): string
$version = MysqlExplain::$VERSION;

try {
$response = $this->client->post('/api/v1/plans', [
$response = $this->client->post('/v2/explains', [
'base_uri' => $this->domain,
'headers' => [
'User-Agent' => "tpetry/laravel-mysql-explain@{$version}",
],
'json' => [
'query' => $metrics->getQuery(),
'version' => $metrics->getVersion(),
'explain_traditional' => $metrics->getExplainTraditional(),
'explain_json' => $metrics->getExplainJson(),
'explain_tree' => $metrics->getExplainTree(),
'warnings' => $metrics->getWarnings(),
],
]);

Expand Down
9 changes: 0 additions & 9 deletions src/Helpers/DatabaseHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,6 @@ public function driverName(Connection $db): string
return $db->getDriverName();
}

/**
* @param mixed[] $bindings
* @return array<int, array<string, int|float|string|null>>
*/
public function queryAssoc(Connection $db, string $sql, array $bindings = []): array
{
return $this->executeQuery($db, $sql, $bindings, fn (PDOStatement $statement) => $statement->fetchAll(PDO::FETCH_ASSOC));
}

/**
* @param mixed[] $bindings
* @return int|float|string|null
Expand Down
4 changes: 0 additions & 4 deletions src/MysqlExplain.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,14 @@ private function collectQueryMetrics(ConnectionInterface $connection, string $sq

$query = $db->buildRawSql($connection, $sql, $bindings);
$version = $db->queryScalar($connection, 'SELECT VERSION()');
$explainTraditional = $db->queryAssoc($connection, "EXPLAIN FORMAT=TRADITIONAL {$sql}", $bindings);
$warnings = $db->queryAssoc($connection, 'SHOW WARNINGS');
$explainJson = $db->queryScalar($connection, "EXPLAIN FORMAT=JSON {$sql}", $bindings);
$explainTree = rescue(fn () => $db->queryScalar($connection, "EXPLAIN FORMAT=TREE {$sql}", $bindings), null, false);

return new QueryMetrics(
query: $query,
version: $version,
explainTraditional: $explainTraditional,
explainJson: $explainJson,
explainTree: $explainTree,
warnings: $warnings,
);
}
}
41 changes: 0 additions & 41 deletions src/Values/QueryMetrics.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@

/**
* @internal
*
* @phpstan-type ExplainTraditional array<int, mixed>
* @phpstan-type Warnings array<int, mixed>
*/
class QueryMetrics
{
Expand All @@ -17,13 +14,6 @@ class QueryMetrics
*/
private string $explainJSON;

/**
* The EXPLAIN FORMAT=TRADITIONAL output.
*
* @type ExplainTraditional
*/
private array $explainTraditional;

/**
* The EXPLAIN FORMAT=TREE output.
*/
Expand All @@ -39,46 +29,23 @@ class QueryMetrics
*/
private string $version;

/**
* The query metrics generated by SHOW WARNINGS.
*
* @type Warnings
*/
private ?array $warnings;

/**
* @param ExplainTraditional $explainTraditional
* @param Warnings $warnings
*/
public function __construct(
string $query,
string $version,
array $explainTraditional,
string $explainJson,
?string $explainTree = null,
?array $warnings = null,
) {
$this->query = $query;
$this->version = $version;
$this->explainTraditional = $explainTraditional;
$this->explainJSON = $explainJson;
$this->explainTree = $explainTree;
$this->warnings = $warnings;
}

public function getExplainJson(): string
{
return $this->explainJSON;
}

/**
* @return ExplainTraditional
*/
public function getExplainTraditional(): array
{
return $this->explainTraditional;
}

public function getExplainTree(): ?string
{
return $this->explainTree;
Expand All @@ -93,12 +60,4 @@ public function getVersion(): string
{
return $this->version;
}

/**
* @return Warnings
*/
public function getWarnings(): ?array
{
return $this->warnings;
}
}
8 changes: 3 additions & 5 deletions tests/Helpers/ApiHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,22 @@ public function testAaa(): void
),
history: $history,
);
$apiHelper = new ApiHelper('https://some-random-domain.local', $client);
$apiHelper = new ApiHelper('https://api.some-random-domain.local', $client);

$queryMetrics = new QueryMetrics(
query: '...query...',
version: '...version...',
explainTraditional: ['...explain traditional...'],
explainJson: '...explain json...',
explainTree: '...explain tree...',
warnings: ['...warnings...'],
);
$url = $apiHelper->submitPlan($queryMetrics);

$this->assertEquals('https://dummy-url-W2lDgjGDl1.local/4XvzCcPWKW', $url);
$this->assertCount(1, $history);
$this->assertEquals('POST', $history[0]['request']->getMethod());
$this->assertEquals('https://some-random-domain.local/api/v1/plans', (string) $history[0]['request']->getUri());
$this->assertEquals('https://api.some-random-domain.local/v2/explains', (string) $history[0]['request']->getUri());
$this->assertEquals(['application/json'], $history[0]['request']->getHeader('Content-Type'));
$this->assertEquals('{"query":"...query...","version":"...version...","explain_traditional":["...explain traditional..."],"explain_json":"...explain json...","explain_tree":"...explain tree...","warnings":["...warnings..."]}', $history[0]['request']->getBody());
$this->assertEquals('{"query":"...query...","version":"...version...","explain_json":"...explain json...","explain_tree":"...explain tree..."}', $history[0]['request']->getBody());
}

private function createGuzzleMock(Response $response, array &$history): Client
Expand Down
12 changes: 0 additions & 12 deletions tests/MysqlExplainTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,6 @@ public function testSubmitQueryCollectsMetricsAndSubmitsThem(): void
$mock->shouldReceive('queryScalar')
->withArgs([$connection, 'EXPLAIN FORMAT=TREE SELECT * FROM customer WHERE last_name = ?', ['SMITH']])
->andReturn('...explain tree...');
$mock->shouldReceive('queryAssoc')
->withArgs([$connection, 'EXPLAIN FORMAT=TRADITIONAL SELECT * FROM customer WHERE last_name = ?', ['SMITH']])
->andReturn(['...explain traditional...']);
$mock->shouldReceive('queryAssoc')
->withArgs([$connection, 'SHOW WARNINGS'])
->andReturn(['...warnings...']);
});
$this->mock(ApiHelper::class, function (MockInterface $mock): void {
$mock->shouldReceive('submitPlan')
Expand All @@ -66,18 +60,12 @@ public function testSubmitQueryCollectsMetricsAndSubmitsThem(): void
if ($arg->getVersion() !== '...version...') {
return false;
}
if ($arg->getExplainTraditional() !== ['...explain traditional...']) {
return false;
}
if ($arg->getExplainJson() !== '...explain json...') {
return false;
}
if ($arg->getExplainTree() !== '...explain tree...') {
return false;
}
if ($arg->getWarnings() !== ['...warnings...']) {
return false;
}

return true;
})
Expand Down

0 comments on commit 218a444

Please sign in to comment.