Skip to content

Commit 2e6a20c

Browse files
committed
Adding buildPreparedStatement method that can have cached results
1 parent 15fca41 commit 2e6a20c

39 files changed

+164
-105
lines changed

.travis.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
language: php
22

33
php:
4-
- 5.6
5-
- 7.0
6-
- 7.1
7-
- 7.2
4+
- "7.1"
5+
- "7.3"
86

97
env:
108
matrix:
@@ -16,6 +14,7 @@ before_script:
1614

1715
script:
1816
- vendor/bin/phpunit
17+
- composer phpstan
1918

2019
after_script:
2120
- php vendor/bin/coveralls -v

composer.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
}
1414
],
1515
"require": {
16-
"php": ">=5.3.0",
16+
"php": ">=7.1.0",
1717
"mouf/utils.common.conditioninterface": "~2.0",
1818
"mouf/utils.value.value-interface": "~1.0",
1919
"mouf/utils.common.paginable-interface": "~1.0",
@@ -24,9 +24,10 @@
2424
"doctrine/cache": "^1.5"
2525
},
2626
"require-dev": {
27-
"phpunit/phpunit": "~5.0",
27+
"phpunit/phpunit": "^7.5.10",
2828
"satooshi/php-coveralls": "~1.0",
29-
"doctrine/dbal": "~2.5"
29+
"doctrine/dbal": "~2.5",
30+
"phpstan/phpstan": "^0.11.7"
3031
},
3132
"suggest": {
3233
"doctrine/dbal": "To support more databases than just MySQL and to use MagicJoin feature",
@@ -64,5 +65,8 @@
6465
}
6566
},
6667
"minimum-stability": "dev",
67-
"prefer-stable": true
68+
"prefer-stable": true,
69+
"scripts": {
70+
"phpstan": "vendor/bin/phpstan analyse -c phpstan.neon src"
71+
}
6872
}

doc/discard_unused_parameters.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,15 @@ $sql = $magicQuery->build($sql, []);
9898
// $sql == "SELECT * FROM products p WHERE status2 = null"
9999
```
100100

101+
####Working with prepared statements
102+
103+
The `MagicQuery::build` method will remove unused parameters AND replace placeholders with the values.
104+
If you are looking for the best possible performance, you can use the alternative `MagicQuery::buildPreparedStatement` method.
105+
106+
The "buildPreparedStatement" method is removing unused parameters BUT it does not replace placeholders.
107+
As a result, MagicQuery can perform some more internal caching and if you have many similar requests,
108+
you will get some performance gains.
109+
101110
###Other alternatives
102111

103112
To avoid concatenating strings, frameworks and libraries have used different strategies. Using a full ORM (like

phpstan.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
parameters:
2+
level: 3
3+
ignoreErrors:
4+
- "#Mouf\\\\MoufManager#"
5+
- "#Mouf\\\\MoufInstanceDescriptor#"

phpunit.xml.dist

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
convertWarningsToExceptions="true"
99
processIsolation="false"
1010
stopOnFailure="false"
11-
syntaxCheck="false"
1211
bootstrap="tests/bootstrap.php"
1312
>
1413

@@ -31,7 +30,7 @@
3130
</whitelist>
3231
</filter>
3332
<logging>
34-
<log type="coverage-html" target="build/coverage" charset="UTF-8" yui="true" highlight="true"/>
33+
<log type="coverage-html" target="build/coverage" />
3534
<log type="coverage-clover" target="build/logs/clover.xml"/>
3635
</logging>
3736
</phpunit>

src/Mouf/Database/MagicQuery.php

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
namespace Mouf\Database;
44

5+
use function array_filter;
6+
use function array_keys;
57
use Doctrine\Common\Cache\VoidCache;
68
use function hash;
9+
use function implode;
710
use Mouf\Database\MagicQuery\Twig\SqlTwigEnvironmentFactory;
811
use Mouf\Database\SchemaAnalyzer\SchemaAnalyzer;
912
use PHPSQLParser\PHPSQLParser;
@@ -85,13 +88,36 @@ public function build($sql, array $parameters = array())
8588
$sql = $this->getTwigEnvironment()->render($sql, $parameters);
8689
}
8790

91+
$select = $this->parse($sql);
92+
$newSql = $this->toSql($select, $parameters, true);
93+
94+
return $newSql;
95+
}
96+
97+
/**
98+
* Returns modified SQL from $sql and $parameters. Any parameters not available will be striped down
99+
* from the SQL. Unlike with the `build` method, the parameters are NOT merged into the SQL.
100+
* This method is more efficient than `build` (because result is cached and statements interpolation
101+
* can be delegated to the database.
102+
*
103+
* @param string $sql
104+
* @param array $parameters
105+
*
106+
* @return string
107+
*/
108+
public function buildPreparedStatement(string $sql, array $parameters = []): string
109+
{
110+
if ($this->enableTwig) {
111+
$sql = $this->getTwigEnvironment()->render($sql, $parameters);
112+
}
113+
88114
$availableParameterKeys = array_keys(array_filter($parameters, static function($param) { return $param !== null;}));
89115
// We choose md4 because it is fast.
90116
$cacheKey = 'request_build_'.hash('md4', $sql.'__'.implode('_/_', $availableParameterKeys));
91117
$newSql = $this->cache->fetch($cacheKey);
92118
if ($newSql === false) {
93119
$select = $this->parse($sql);
94-
$newSql = $this->toSql($select, $parameters);
120+
$newSql = $this->toSql($select, $parameters, false);
95121

96122
$this->cache->save($cacheKey, $newSql);
97123
}
@@ -140,13 +166,14 @@ public function parse($sql)
140166
* Transforms back a tree of SQL node into a SQL string.
141167
*
142168
* @param NodeInterface $sqlNode
143-
* @param array $parameters
144-
*
169+
* @param array $parameters
170+
* @param bool $extrapolateParameters Whether the parameters should be fed into the returned SQL query
171+
145172
* @return string
146173
*/
147-
public function toSql(NodeInterface $sqlNode, array $parameters = array())
174+
public function toSql(NodeInterface $sqlNode, array $parameters = array(), bool $extrapolateParameters = true)
148175
{
149-
return $sqlNode->toSql($parameters, $this->connection, 0, SqlRenderInterface::CONDITION_GUESS);
176+
return $sqlNode->toSql($parameters, $this->connection, 0, SqlRenderInterface::CONDITION_GUESS, $extrapolateParameters);
150177
}
151178

152179
/**

src/Mouf/Database/QueryWriter/Condition/ParamAvailableCondition.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ public function __construct($parameterName)
2323
$this->parameterName = $parameterName;
2424
}
2525

26-
/**
27-
* @param string $caller
28-
*/
2926
public function isOk($parameters = null)
3027
{
3128
return isset($parameters[$this->parameterName]) && !empty($parameters[$this->parameterName]);

src/Mouf/Database/QueryWriter/Condition/ParamEqualsCondition.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ public function __construct($parameterName, $value)
2828
$this->value = $value;
2929
}
3030

31-
/**
32-
* @param string $caller
33-
*/
3431
public function isOk($parameters = null)
3532
{
3633
return isset($parameters[$this->parameterName]) && $parameters[$this->parameterName] == ValueUtils::val($this->value);

src/Mouf/Database/QueryWriter/Condition/ParamNotAvailableCondition.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ public function __construct($parameterName)
2323
$this->parameterName = $parameterName;
2424
}
2525

26-
/**
27-
* @param string $caller
28-
*/
2926
public function isOk($parameters = null)
3027
{
3128
return !isset($parameters[$this->parameterName]) || empty($parameters[$this->parameterName]);

src/SQLParser/Node/AbstractManyInstancesOperator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,11 @@ public function toInstanceDescriptor(MoufManager $moufManager)
6363
*
6464
* @return string
6565
*/
66-
public function toSql(array $parameters = array(), Connection $dbConnection = null, $indent = 0, $conditionsMode = self::CONDITION_APPLY)
66+
public function toSql(array $parameters = array(), Connection $dbConnection = null, $indent = 0, $conditionsMode = self::CONDITION_APPLY, bool $extrapolateParameters = true)
6767
{
6868
$sqlOperands = array();
6969
foreach ($this->operands as $operand) {
70-
$sql = NodeFactory::toSql($operand, $dbConnection, $parameters, ' ', true, $indent, $conditionsMode);
70+
$sql = NodeFactory::toSql($operand, $dbConnection, $parameters, ' ', true, $indent, $conditionsMode, $extrapolateParameters);
7171
if ($sql != null) {
7272
$sqlOperands[] = $sql;
7373
}

0 commit comments

Comments
 (0)