Skip to content

Commit 6461623

Browse files
committed
Transforms automatically '= null' into 'IS NULL'. Closes database.tdbm/issues#75
1 parent edfb576 commit 6461623

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+375
-277
lines changed

src/Mouf/Database/MagicQuery.php

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ class MagicQuery
3434
private $enableTwig = false;
3535

3636
/**
37-
* @param \Doctrine\DBAL\Connection $connection
37+
* @param \Doctrine\DBAL\Connection $connection
3838
* @param \Doctrine\Common\Cache\Cache $cache
39-
* @param SchemaAnalyzer $schemaAnalyzer (optional). If not set, it is initialized from the connection.
39+
* @param SchemaAnalyzer $schemaAnalyzer (optional). If not set, it is initialized from the connection.
4040
*/
4141
public function __construct($connection = null, $cache = null, SchemaAnalyzer $schemaAnalyzer = null)
4242
{
@@ -54,11 +54,15 @@ public function __construct($connection = null, $cache = null, SchemaAnalyzer $s
5454
/**
5555
* Whether Twig parsing should be enabled or not.
5656
* Defaults to false.
57+
*
5758
* @param bool $enableTwig
59+
*
5860
* @return $this
5961
*/
60-
public function setEnableTwig($enableTwig = true) {
62+
public function setEnableTwig($enableTwig = true)
63+
{
6164
$this->enableTwig = $enableTwig;
65+
6266
return $this;
6367
}
6468

@@ -79,6 +83,7 @@ public function build($sql, array $parameters = array())
7983
$sql = $this->getTwigEnvironment()->render($sql, $parameters);
8084
}
8185
$select = $this->parse($sql);
86+
8287
return $this->toSql($select, $parameters);
8388
}
8489

@@ -87,13 +92,16 @@ public function build($sql, array $parameters = array())
8792
* This tree representation can be used to manipulate the SQL.
8893
*
8994
* @param string $sql
95+
*
9096
* @return NodeInterface
97+
*
9198
* @throws MagicQueryMissingConnectionException
9299
* @throws MagicQueryParserException
93100
*/
94-
public function parse($sql) {
101+
public function parse($sql)
102+
{
95103
// We choose md4 because it is fast.
96-
$cacheKey = "request_".hash("md4", $sql);
104+
$cacheKey = 'request_'.hash('md4', $sql);
97105
$select = $this->cache->fetch($cacheKey);
98106

99107
if ($select === false) {
@@ -111,27 +119,32 @@ public function parse($sql) {
111119
// Let's store the tree
112120
$this->cache->save($cacheKey, $select);
113121
}
122+
114123
return $select;
115124
}
116125

117126
/**
118127
* Transforms back a tree of SQL node into a SQL string.
119128
*
120129
* @param NodeInterface $sqlNode
121-
* @param array $parameters
130+
* @param array $parameters
131+
*
122132
* @return string
123133
*/
124-
public function toSql(NodeInterface $sqlNode, array $parameters = array()) {
134+
public function toSql(NodeInterface $sqlNode, array $parameters = array())
135+
{
125136
return $sqlNode->toSql($parameters, $this->connection, 0, SqlRenderInterface::CONDITION_GUESS);
126137
}
127138

128139
/**
129140
* Scans the SQL statement and replaces the "magicjoin" part with the correct joins.
130141
*
131142
* @param NodeInterface $select
143+
*
132144
* @throws MagicQueryMissingConnectionException
133145
*/
134-
private function magicJoin(NodeInterface $select) {
146+
private function magicJoin(NodeInterface $select)
147+
{
135148
// Let's find if this is a MagicJoin query.
136149
$magicJoinDetector = new DetectMagicJoinSelectVisitor();
137150
$nodeTraverser = new NodeTraverser();
@@ -147,11 +160,14 @@ private function magicJoin(NodeInterface $select) {
147160
}
148161

149162
/**
150-
* For one given MagicJoin select, let's apply MagicJoin
163+
* For one given MagicJoin select, let's apply MagicJoin.
164+
*
151165
* @param MagicJoinSelect $magicJoinSelect
166+
*
152167
* @return Select
153168
*/
154-
private function magicJoinOnOneQuery(MagicJoinSelect $magicJoinSelect) {
169+
private function magicJoinOnOneQuery(MagicJoinSelect $magicJoinSelect)
170+
{
155171
$tableSearchNodeTraverser = new NodeTraverser();
156172
$detectTableVisitor = new DetectTablesVisitor($magicJoinSelect->getMainTable());
157173
$tableSearchNodeTraverser->addVisitor($detectTableVisitor);
@@ -183,7 +199,7 @@ private function magicJoinOnOneQuery(MagicJoinSelect $magicJoinSelect) {
183199
$tableNode = new Table();
184200
$tableNode->setTable($mainTable);
185201
$tables = [
186-
$mainTable => $tableNode
202+
$mainTable => $tableNode,
187203
];
188204

189205
foreach ($completePath as $foreignKey) {
@@ -202,7 +218,7 @@ private function magicJoinOnOneQuery(MagicJoinSelect $magicJoinSelect) {
202218
$onNode->setRightOperand($rightCol);
203219

204220
$tableNode = new Table();
205-
$tableNode->setJoinType("LEFT JOIN");
221+
$tableNode->setJoinType('LEFT JOIN');
206222
$tableNode->setRefClause($onNode);
207223

208224
if (isset($tables[$foreignKey->getLocalTableName()])) {
@@ -215,34 +231,38 @@ private function magicJoinOnOneQuery(MagicJoinSelect $magicJoinSelect) {
215231
}
216232

217233
$select->setFrom($tables);
218-
219234
}
220235

221236
/**
222237
* @return SchemaAnalyzer
223238
*/
224-
private function getSchemaAnalyzer() {
239+
private function getSchemaAnalyzer()
240+
{
225241
if ($this->schemaAnalyzer === null) {
226242
if (!$this->connection) {
227243
throw new MagicQueryMissingConnectionException('In order to use MagicJoin, you need to configure a DBAL connection.');
228244
}
229245

230246
$this->schemaAnalyzer = new SchemaAnalyzer($this->connection->getSchemaManager(), $this->cache, $this->getConnectionUniqueId());
231247
}
248+
232249
return $this->schemaAnalyzer;
233250
}
234251

235-
private function getConnectionUniqueId() {
236-
return hash('md4', $this->connection->getHost()."-".$this->connection->getPort()."-".$this->connection->getDatabase()."-".$this->connection->getDriver()->getName());
252+
private function getConnectionUniqueId()
253+
{
254+
return hash('md4', $this->connection->getHost().'-'.$this->connection->getPort().'-'.$this->connection->getDatabase().'-'.$this->connection->getDriver()->getName());
237255
}
238256

239257
/**
240258
* @return \Twig_Environment
241259
*/
242-
private function getTwigEnvironment() {
260+
private function getTwigEnvironment()
261+
{
243262
if ($this->twigEnvironment === null) {
244263
$this->twigEnvironment = SqlTwigEnvironmentFactory::getTwigEnvironment();
245264
}
265+
246266
return $this->twigEnvironment;
247267
}
248268
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<?php
2+
23
namespace Mouf\Database\MagicQuery\Twig;
34

45
use Mouf\Database\MagicQueryException;
56

67
class ForbiddenTwigParameterInSqlException extends MagicQueryException
78
{
8-
9-
}
9+
}

src/Mouf/Database/MagicQuery/Twig/SqlTwigEnvironmentFactory.php

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
<?php
2-
namespace Mouf\Database\MagicQuery\Twig;
32

4-
use Doctrine\DBAL\Connection;
3+
namespace Mouf\Database\MagicQuery\Twig;
54

65
/**
7-
* Class in charge of creating the Twig environment
6+
* Class in charge of creating the Twig environment.
87
*/
98
class SqlTwigEnvironmentFactory
109
{
1110
private static $twig;
1211

13-
public static function getTwigEnvironment() {
12+
public static function getTwigEnvironment()
13+
{
1414
if (self::$twig) {
1515
return self::$twig;
1616
}
@@ -20,14 +20,14 @@ public static function getTwigEnvironment() {
2020
$options = array(
2121
// The cache directory is in the temporary directory and reproduces the path to the directory (to avoid cache conflict between apps).
2222
'cache' => self::getCacheDirectory(),
23-
'strict_variables' => true
23+
'strict_variables' => true,
2424
);
2525

2626
$twig = new \Twig_Environment($stringLoader, $options);
2727

2828
// Default escaper will throw an exception. This is because we want to use SQL parameters instead of Twig.
2929
// This ahs a number of advantages, especially in terms of caching.
30-
$twig->getExtension('core')->setEscaper('sql', function() {
30+
$twig->getExtension('core')->setEscaper('sql', function () {
3131
throw new ForbiddenTwigParameterInSqlException('You cannot use Twig expressions (like "{{ id }}"). Instead, you should use SQL parameters (like ":id"). Twig integration is limited to Twig statements (like "{% for .... %}"');
3232
});
3333

@@ -39,7 +39,8 @@ public static function getTwigEnvironment() {
3939
return $twig;
4040
}
4141

42-
private static function getCacheDirectory() {
42+
private static function getCacheDirectory()
43+
{
4344
// If we are running on a Unix environment, let's prepend the cache with the user id of the PHP process.
4445
// This way, we can avoid rights conflicts.
4546

@@ -50,7 +51,7 @@ private static function getCacheDirectory() {
5051
$posixGetuid = '';
5152
}
5253
// @codeCoverageIgnoreEnd
53-
$cacheDirectory = rtrim(sys_get_temp_dir(), '/\\').'/magicquerysqltwigtemplate'.$posixGetuid.str_replace(":", "", __DIR__);
54+
$cacheDirectory = rtrim(sys_get_temp_dir(), '/\\').'/magicquerysqltwigtemplate'.$posixGetuid.str_replace(':', '', __DIR__);
5455

5556
return $cacheDirectory;
5657
}

src/Mouf/Database/MagicQuery/Twig/StringLoader.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
2-
namespace Mouf\Database\MagicQuery\Twig;
32

3+
namespace Mouf\Database\MagicQuery\Twig;
44

55
/**
66
* This loader completely bypasses the loader mechanism, by directly passing the key as a template.
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
<?php
2-
namespace Mouf\Database;
32

3+
namespace Mouf\Database;
44

55
class MagicQueryMissingConnectionException extends MagicQueryException
66
{
7-
8-
}
7+
}

src/SQLParser/ExpressionType.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
3232
* DAMAGE.
3333
*/
34-
3534
namespace SQLParser;
3635

3736
class ExpressionType

src/SQLParser/InvalidParameterException.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
3232
* DAMAGE.
3333
*/
34-
3534
namespace SQLParser;
3635

3736
class InvalidParameterException extends \InvalidArgumentException

src/SQLParser/LexerSplitter.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
3232
* DAMAGE.
3333
*/
34-
3534
namespace SQLParser;
3635

3736
class LexerSplitter

src/SQLParser/Node/AbstractManyInstancesOperator.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ public function toSql(array $parameters = array(), Connection $dbConnection = nu
8181
*
8282
* @param VisitorInterface $visitor
8383
*/
84-
public function walk(VisitorInterface $visitor) {
84+
public function walk(VisitorInterface $visitor)
85+
{
8586
$node = $this;
8687
$result = $visitor->enterNode($node);
8788
if ($result instanceof NodeInterface) {
@@ -97,6 +98,7 @@ public function walk(VisitorInterface $visitor) {
9798
}
9899
}
99100
}
101+
100102
return $visitor->leaveNode($node);
101103
}
102104

src/SQLParser/Node/AbstractTwoOperandsOperator.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,22 +117,30 @@ public function toSql(array $parameters = array(), Connection $dbConnection = nu
117117
}
118118
}
119119
if ($conditionsMode == self::CONDITION_IGNORE || !$this->condition || $this->condition->isOk($parameters)) {
120-
$sql = NodeFactory::toSql($this->leftOperand, $dbConnection, $parameters, ' ', false, $indent, $conditionsMode);
121-
$sql .= ' '.$this->getOperatorSymbol().' ';
122-
$sql .= NodeFactory::toSql($this->rightOperand, $dbConnection, $parameters, ' ', false, $indent, $conditionsMode);
120+
$sql = $this->getSql($parameters, $dbConnection, $indent, $conditionsMode);
123121
} else {
124122
$sql = null;
125123
}
126124

127125
return $sql;
128126
}
129127

128+
protected function getSql(array $parameters = array(), Connection $dbConnection = null, $indent = 0, $conditionsMode = self::CONDITION_APPLY)
129+
{
130+
$sql = NodeFactory::toSql($this->leftOperand, $dbConnection, $parameters, ' ', false, $indent, $conditionsMode);
131+
$sql .= ' '.$this->getOperatorSymbol().' ';
132+
$sql .= NodeFactory::toSql($this->rightOperand, $dbConnection, $parameters, ' ', false, $indent, $conditionsMode);
133+
134+
return $sql;
135+
}
136+
130137
/**
131138
* Walks the tree of nodes, calling the visitor passed in parameter.
132139
*
133140
* @param VisitorInterface $visitor
134141
*/
135-
public function walk(VisitorInterface $visitor) {
142+
public function walk(VisitorInterface $visitor)
143+
{
136144
$node = $this;
137145
$result = $visitor->enterNode($node);
138146
if ($result instanceof NodeInterface) {
@@ -153,10 +161,10 @@ public function walk(VisitorInterface $visitor) {
153161
$this->rightOperand = $result2;
154162
}
155163
}
164+
156165
return $visitor->leaveNode($node);
157166
}
158167

159-
160168
/**
161169
* Returns the symbol for this operator.
162170
*/

0 commit comments

Comments
 (0)