Skip to content

Commit e790cbf

Browse files
authored
Laravel SQLCommenter (#113)
Initial checkin of laravel-sqlcommenter (PHP). This PR contains the library code, few utilities and unit tests for utilities. In the next set of PRs, integration tests will be added.
1 parent e1d9a49 commit e790cbf

14 files changed

Lines changed: 922 additions & 0 deletions

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ Contains all the various `sqlcommenter-*` implementations.
1616
- [X] [Node.js](nodejs/sqlcommenter-nodejs/README.md)
1717
- [X] [Knex.js](nodejs/sqlcommenter-nodejs/packages/sqlcommenter-knex/README.md)
1818
- [X] [Sequelize.js](nodejs/sqlcommenter-nodejs/packages/sqlcommenter-sequelize/README.md)
19+
- [X] Php
20+
- [X] [Laravel](php/sqlcommenter-php/packages/sqlcommenter-laravel)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# sqlcommenter-laravel [In Development]
2+
3+
sqlcommenter is a plugin/middleware/wrapper to augment SQL statements from laravel
4+
with comments that can be used later to correlate user code with SQL statements.
5+
6+
7+
### Installation
8+
9+
Add this to your composer.json
10+
```shell
11+
"repositories": [
12+
{
13+
"type": "path",
14+
"url": "/full/or/relative/path/to/sqlcommenter-laravel/package"
15+
}
16+
]
17+
```
18+
Install the package
19+
```shell
20+
composer require "google/sqlcommenter-laravel"
21+
```
22+
### Usage
23+
24+
Publish the config file from library to into laravel app using below command
25+
26+
```shell
27+
php artisan vendor:publish --provider="google\GoogleSqlCommenterLaravel\GoogleSqlCommenterServiceProvider"
28+
```
29+
30+
Add the following class above ``Illuminate\Database\DatabaseServiceProvider::class,
31+
`` in config/app.php
32+
```php
33+
'providers' => [
34+
...
35+
Google\GoogleSqlCommenterLaravel\Database\DatabaseServiceProvider::class,
36+
Illuminate\Database\DatabaseServiceProvider::class,
37+
...
38+
]
39+
```
40+
### Run the tests
41+
42+
Run the tests using below command
43+
```shell
44+
./vendor/bin/phpunit tests
45+
```
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"name": "google/sqlcommenter-laravel",
3+
"description": "Laravel middleware to send events to OpenTelemetry",
4+
"type": "library",
5+
"license": "MIT",
6+
"authors": [
7+
{
8+
"name": "Google Developers",
9+
"email": "sqlcommenter@googlegroups.com",
10+
"role": "Developer"
11+
}],
12+
"require": {
13+
"open-telemetry/opentelemetry": "~0.0.9",
14+
"php-http/guzzle7-adapter": "^1.0"
15+
},
16+
"autoload": {
17+
"psr-4": {
18+
"Google\\GoogleSqlCommenterLaravel\\": "src"
19+
},
20+
"classmap": [
21+
"src/"
22+
]
23+
},
24+
"extra": {
25+
"laravel": {
26+
"providers": [
27+
"Google\\GoogleSqlCommenterLaravel\\GoogleSqlCommenterServiceProvider"
28+
]
29+
}
30+
},
31+
"scripts": {
32+
"format": "phpcbf --standard=psr2 src/"
33+
},
34+
"require-dev": {
35+
"phpunit/phpunit": "^9.5"
36+
}
37+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<?php
2+
/*
3+
* Copyright 2022 Google LLC
4+
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
9+
* http:*www.apache.org/licenses/LICENSE-2.0
10+
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
namespace Google\GoogleSqlCommenterLaravel\Database;
19+
20+
use Illuminate\Database\Connection as BaseConnection;
21+
use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator;
22+
use Google\GoogleSqlCommenterLaravel\Opentelemetry;
23+
use Google\GoogleSqlCommenterLaravel\Utils;
24+
25+
26+
class Connection extends BaseConnection
27+
{
28+
/**
29+
* Run a select statement and return a single result.
30+
*
31+
* @param string $query
32+
* @param array $bindings
33+
* @param bool $useReadPdo
34+
* @return mixed
35+
*/
36+
public function selectOne($query, $bindings = [], $useReadPdo = true)
37+
{
38+
$query .= $this->getSqlComments();
39+
$records = parent::select($query, $bindings, $useReadPdo);
40+
41+
if (count($records) > 0) {
42+
return $records;
43+
}
44+
return null;
45+
}
46+
47+
/**
48+
* Run a select statement against the database.
49+
*
50+
* @param string $query
51+
* @param array $bindings
52+
* @param bool $useReadPdo
53+
* @return array
54+
*/
55+
public function select($query, $bindings = [], $useReadPdo = true)
56+
{
57+
$query .= $this->getSqlComments();
58+
$records = parent::select($query, $bindings, $useReadPdo);
59+
return $records;
60+
}
61+
62+
/**
63+
* Run an insert statement against the database.
64+
*
65+
* @param string $query
66+
* @param array $bindings
67+
* @return bool
68+
*/
69+
public function insert($query, $bindings = [])
70+
{
71+
$query .= $this->getSqlComments();
72+
73+
$records = parent::insert($query, $bindings);
74+
75+
return $records;
76+
}
77+
78+
/**
79+
* Run an update statement against the database.
80+
*
81+
* @param string $query
82+
* @param array $bindings
83+
* @return int
84+
*/
85+
public function update($query, $bindings = [])
86+
{
87+
$query .= $this->getSqlComments();
88+
89+
return $this->affectingStatement($query, $bindings);
90+
}
91+
92+
/**
93+
* Run a delete statement against the database.
94+
*
95+
* @param string $query
96+
* @param array $bindings
97+
* @return int
98+
*/
99+
public function delete($query, $bindings = [])
100+
{
101+
$query .= $this->getSqlComments();
102+
103+
return $this->affectingStatement($query, $bindings);
104+
}
105+
106+
private function getSqlComments()
107+
{
108+
$configurationKey = 'google_sqlcommenter.include.';
109+
$comment = [];
110+
$action = null;
111+
112+
if (!empty(app('request')->route())) {
113+
$action = app('request')->route()->getAction();
114+
}
115+
if (config($configurationKey . 'framework', true)) {
116+
$comment['framework'] = "laravel-" . app()->version();
117+
}
118+
if (config($configurationKey . 'controller', true) and !empty($action['controller'])) {
119+
$comment['controller'] = explode("@", class_basename($action['controller']))[0];
120+
}
121+
if (config($configurationKey . 'action', true) and !empty($action['controller'] and str_contains($action['controller'], '@'))) {
122+
$comment['action'] = explode("@", class_basename($action['controller']))[1];
123+
}
124+
if (config($configurationKey . 'route', true)) {
125+
$comment['route'] = request()->getRequestUri();
126+
}
127+
if (config($configurationKey . 'db_driver', true)) {
128+
$connection = config('database.default');
129+
$comment['db_driver'] = config("database.connections.{$connection}.driver");
130+
}
131+
if (config($configurationKey . 'opentelemetry', true)) {
132+
$carrier = Opentelemetry::getOpentelemetryValues();
133+
$comment = array_merge($comment, $carrier);
134+
}
135+
return Utils::formatComments(array_filter(($comment)));
136+
}
137+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
/*
3+
* Copyright 2022 Google LLC
4+
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
9+
* http:*www.apache.org/licenses/LICENSE-2.0
10+
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
namespace Google\GoogleSqlCommenterLaravel\Database;
19+
20+
use Illuminate\Support\ServiceProvider;
21+
22+
class DatabaseServiceProvider extends ServiceProvider
23+
{
24+
/**
25+
* Register the service provider.
26+
*
27+
* @return void
28+
*/
29+
public function boot()
30+
{
31+
32+
Connection::resolverFor('mysql', function ($connection, $database, $prefix, $config) {
33+
return new MySqlConnection($connection, $database, $prefix, $config);
34+
});
35+
36+
Connection::resolverFor('pgsql', function ($connection, $database, $prefix, $config) {
37+
return new PostgresConnection($connection, $database, $prefix, $config);
38+
});
39+
40+
Connection::resolverFor('sqlite', function ($connection, $database, $prefix, $config) {
41+
return new SQLiteConnection($connection, $database, $prefix, $config);
42+
});
43+
44+
Connection::resolverFor('sqlsrv', function ($connection, $database, $prefix, $config) {
45+
return new SqlServerConnection($connection, $database, $prefix, $config);
46+
});
47+
}
48+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
/*
3+
* Copyright 2022 Google LLC
4+
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
9+
* http:*www.apache.org/licenses/LICENSE-2.0
10+
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
namespace Google\GoogleSqlCommenterLaravel\Database;
19+
20+
use Illuminate\Database\PDO\MySqlDriver;
21+
use Illuminate\Database\Query\Grammars\MySqlGrammar as QueryGrammar;
22+
use Illuminate\Database\Query\Processors\MySqlProcessor;
23+
use Illuminate\Database\Schema\Grammars\MySqlGrammar as SchemaGrammar;
24+
use Illuminate\Database\Schema\MySqlBuilder;
25+
use Illuminate\Database\Schema\MySqlSchemaState;
26+
use Illuminate\Filesystem\Filesystem;
27+
use PDO;
28+
29+
class MySqlConnection extends Connection
30+
{
31+
/**
32+
* Determine if the connected database is a MariaDB database.
33+
*
34+
* @return bool
35+
*/
36+
public function isMaria()
37+
{
38+
return str_contains($this->getPdo()->getAttribute(PDO::ATTR_SERVER_VERSION), 'MariaDB');
39+
}
40+
41+
/**
42+
* Get the default query grammar instance.
43+
*
44+
* @return \Illuminate\Database\Query\Grammars\MySqlGrammar
45+
*/
46+
protected function getDefaultQueryGrammar()
47+
{
48+
return $this->withTablePrefix(new QueryGrammar);
49+
}
50+
51+
/**
52+
* Get a schema builder instance for the connection.
53+
*
54+
* @return \Illuminate\Database\Schema\MySqlBuilder
55+
*/
56+
public function getSchemaBuilder()
57+
{
58+
if (is_null($this->schemaGrammar)) {
59+
$this->useDefaultSchemaGrammar();
60+
}
61+
62+
return new MySqlBuilder($this);
63+
}
64+
65+
/**
66+
* Get the default schema grammar instance.
67+
*
68+
* @return \Illuminate\Database\Schema\Grammars\MySqlGrammar
69+
*/
70+
protected function getDefaultSchemaGrammar()
71+
{
72+
return $this->withTablePrefix(new SchemaGrammar);
73+
}
74+
75+
/**
76+
* Get the schema state for the connection.
77+
*
78+
* @param \Illuminate\Filesystem\Filesystem|null $files
79+
* @param callable|null $processFactory
80+
* @return \Illuminate\Database\Schema\MySqlSchemaState
81+
*/
82+
public function getSchemaState(Filesystem $files = null, callable $processFactory = null)
83+
{
84+
return new MySqlSchemaState($this, $files, $processFactory);
85+
}
86+
87+
/**
88+
* Get the default post processor instance.
89+
*
90+
* @return \Illuminate\Database\Query\Processors\MySqlProcessor
91+
*/
92+
protected function getDefaultPostProcessor()
93+
{
94+
return new MySqlProcessor;
95+
}
96+
97+
/**
98+
* Get the Doctrine DBAL driver.
99+
*
100+
* @return \Illuminate\Database\PDO\MySqlDriver
101+
*/
102+
protected function getDoctrineDriver()
103+
{
104+
return new MySqlDriver;
105+
}
106+
}

0 commit comments

Comments
 (0)