Skip to content

Commit 4f8555a

Browse files
committed
Starting migration to greenlion/PHP-SQL-Parser
1 parent b303935 commit 4f8555a

File tree

7 files changed

+149
-44
lines changed

7 files changed

+149
-44
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"mouf/utils.common.paginable-interface": "~1.0",
2020
"mouf/utils.common.sortable-interface": "~1.0",
2121
"mouf/schema-analyzer": "~1.0",
22-
"twig/twig": "~1.14"
22+
"twig/twig": "~1.14",
23+
"greenlion/php-sql-parser": "^4.0"
2324
},
2425
"require-dev": {
2526
"phpunit/phpunit": "~5.0",

src/Mouf/Database/MagicQuery.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Doctrine\Common\Cache\VoidCache;
66
use Mouf\Database\MagicQuery\Twig\SqlTwigEnvironmentFactory;
77
use Mouf\Database\SchemaAnalyzer\SchemaAnalyzer;
8+
use PHPSQLParser\PHPSQLParser;
89
use SQLParser\Node\ColRef;
910
use SQLParser\Node\Equal;
1011
use SQLParser\Node\NodeInterface;
@@ -105,7 +106,8 @@ public function parse($sql)
105106
$select = $this->cache->fetch($cacheKey);
106107

107108
if ($select === false) {
108-
$parser = new SQLParser();
109+
//$parser = new SQLParser();
110+
$parser = new PHPSQLParser();
109111
$parsed = $parser->parse($sql);
110112

111113
if ($parsed == false) {

src/SQLParser/Node/ColRef.php

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,28 @@
4343
*/
4444
class ColRef implements NodeInterface
4545
{
46+
private $database;
47+
48+
/**
49+
* Returns the name of the database.
50+
*
51+
* @return mixed
52+
*/
53+
public function getDatabase()
54+
{
55+
return $this->database;
56+
}
57+
58+
/**
59+
* Sets the name of the database
60+
*
61+
* @param mixed $database
62+
*/
63+
public function setDatabase($database)
64+
{
65+
$this->database = $database;
66+
}
67+
4668
private $table;
4769

4870
/**
@@ -149,6 +171,7 @@ public function setDirection($direction)
149171
public function toInstanceDescriptor(MoufManager $moufManager)
150172
{
151173
$instanceDescriptor = $moufManager->createInstance(get_called_class());
174+
$instanceDescriptor->getProperty('database')->setValue($this->database);
152175
$instanceDescriptor->getProperty('table')->setValue($this->table);
153176
$instanceDescriptor->getProperty('column')->setValue($this->column);
154177
$instanceDescriptor->getProperty('alias')->setValue($this->alias);
@@ -170,10 +193,13 @@ public function toInstanceDescriptor(MoufManager $moufManager)
170193
public function toSql(array $parameters = array(), Connection $dbConnection = null, $indent = 0, $conditionsMode = self::CONDITION_APPLY)
171194
{
172195
$sql = '';
196+
if ($this->database) {
197+
$sql .= NodeFactory::escapeDBItem($this->database, $dbConnection).'.';
198+
}
173199
if ($this->table) {
174200
$sql .= NodeFactory::escapeDBItem($this->table, $dbConnection).'.';
175201
}
176-
if ($this->column != '*') {
202+
if ($this->column !== '*') {
177203
$sql .= NodeFactory::escapeDBItem($this->column, $dbConnection);
178204
} else {
179205
$sql .= '*';

src/SQLParser/Node/NodeFactory.php

Lines changed: 73 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -54,32 +54,6 @@ public static function toObject(array $desc)
5454
}
5555

5656
switch ($desc['expr_type']) {
57-
case ExpressionType::LIMIT_CONST:
58-
if (substr($desc['base_expr'], 0, 1) == ':') {
59-
$instance = new UnquotedParameter();
60-
$instance->setName(substr($desc['base_expr'], 1));
61-
} else {
62-
$instance = new LimitNode();
63-
$expr = $desc['base_expr'];
64-
if (strpos($expr, "'") === 0) {
65-
$expr = substr($expr, 1);
66-
}
67-
if (strrpos($expr, "'") === strlen($expr) - 1) {
68-
$expr = substr($expr, 0, strlen($expr) - 1);
69-
}
70-
$expr = stripslashes($expr);
71-
72-
$instance->setValue($expr);
73-
}
74-
// Debug:
75-
unset($desc['base_expr']);
76-
unset($desc['expr_type']);
77-
unset($desc['sub_tree']);
78-
if (!empty($desc)) {
79-
throw new \InvalidArgumentException('Unexpected parameters in exception: '.var_export($desc, true));
80-
}
81-
82-
return $instance;
8357
case ExpressionType::CONSTANT:
8458
$const = new ConstNode();
8559
$expr = $desc['base_expr'];
@@ -113,6 +87,7 @@ public static function toObject(array $desc)
11387
unset($desc['base_expr']);
11488
unset($desc['expr_type']);
11589
unset($desc['sub_tree']);
90+
unset($desc['delim']);
11691

11792
if (!empty($desc)) {
11893
throw new \InvalidArgumentException('Unexpected parameters in exception: '.var_export($desc, true));
@@ -137,18 +112,31 @@ public static function toObject(array $desc)
137112
return $operator;
138113

139114
case ExpressionType::COLREF:
140-
if (substr($desc['base_expr'], 0, 1) == ':') {
115+
if (substr($desc['base_expr'], 0, 1) === ':') {
141116
$instance = new Parameter();
142117
$instance->setName(substr($desc['base_expr'], 1));
143118
} else {
144119
$instance = new ColRef();
145-
$lastDot = strrpos($desc['base_expr'], '.');
146-
if ($lastDot === false) {
147-
$instance->setColumn(str_replace('`', '', $desc['base_expr']));
120+
121+
if (isset($desc['no_quotes'])) {
122+
$parts = $desc['no_quotes']['parts'];
148123
} else {
149-
$instance->setColumn(str_replace('`', '', substr($desc['base_expr'], $lastDot + 1)));
150-
$instance->setTable(str_replace('`', '', substr($desc['base_expr'], 0, $lastDot)));
124+
$parts = explode('.', str_replace('`', '', $desc['base_expr']));
151125
}
126+
127+
$columnName = array_pop($parts);
128+
$instance->setColumn($columnName);
129+
130+
if (!empty($parts)) {
131+
$tableName = array_pop($parts);
132+
$instance->setTable($tableName);
133+
}
134+
135+
if (!empty($parts)) {
136+
$baseName = array_pop($parts);
137+
$instance->setDatabase($baseName);
138+
}
139+
152140
if (!empty($desc['alias'])) {
153141
$instance->setAlias($desc['alias']['name']);
154142
}
@@ -167,13 +155,32 @@ public static function toObject(array $desc)
167155
}
168156
unset($desc['sub_tree']);
169157
unset($desc['alias']);
158+
unset($desc['no_quotes']);
159+
unset($desc['delim']);
170160
if (!empty($desc)) {
171161
throw new \InvalidArgumentException('Unexpected parameters in exception: '.var_export($desc, true));
172162
}
173163

174164
return $instance;
175165
case ExpressionType::TABLE:
176166
$expr = new Table();
167+
168+
if (isset($desc['no_quotes'])) {
169+
$parts = $desc['no_quotes']['parts'];
170+
171+
$tableName = array_pop($parts);
172+
$expr->setTable($tableName);
173+
174+
if (!empty($parts)) {
175+
$baseName = array_pop($parts);
176+
$expr->setDatabase($baseName);
177+
}
178+
} else {
179+
$expr->setTable($desc['table']);
180+
}
181+
182+
183+
177184
$expr->setTable(str_replace('`', '', $desc['table']));
178185
switch ($desc['join_type']) {
179186
case 'CROSS':
@@ -225,6 +232,8 @@ public static function toObject(array $desc)
225232
unset($desc['table']);
226233
unset($desc['ref_type']);
227234
unset($desc['ref_clause']);
235+
unset($desc['hints']);
236+
unset($desc['no_quotes']);
228237
if (!empty($desc)) {
229238
throw new \InvalidArgumentException('Unexpected parameters in exception: '.var_export($desc, true));
230239
}
@@ -279,8 +288,9 @@ public static function toObject(array $desc)
279288
unset($desc['expr_type']);
280289
unset($desc['sub_tree']);
281290
unset($desc['alias']);
291+
unset($desc['delim']);
282292
if (!empty($desc)) {
283-
throw new \InvalidArgumentException('Unexpected parameters in exception: '.var_export($desc, true));
293+
throw new \InvalidArgumentException('Unexpected parameters in aggregate function: '.var_export($desc, true));
284294
}
285295

286296
return $expr;
@@ -305,6 +315,7 @@ public static function toObject(array $desc)
305315
unset($desc['sub_tree']);
306316
unset($desc['alias']);
307317
unset($desc['direction']);
318+
unset($desc['delim']);
308319
if (!empty($desc)) {
309320
throw new \InvalidArgumentException('Unexpected parameters in simple function: '.var_export($desc, true));
310321
}
@@ -393,6 +404,7 @@ public static function toObject(array $desc)
393404
unset($desc['sub_tree']);
394405
unset($desc['alias']);
395406
unset($desc['direction']);
407+
unset($desc['delim']);
396408
if (!empty($desc)) {
397409
throw new \InvalidArgumentException('Unexpected parameters in exception: '.var_export($desc, true));
398410
}
@@ -403,6 +415,34 @@ public static function toObject(array $desc)
403415
}
404416
}
405417

418+
419+
/**
420+
* Transforms a limit or offset value/parameter into a node.
421+
*
422+
* @param string $value
423+
* @return NodeInterface
424+
*/
425+
public static function toLimitNode($value)
426+
{
427+
if (substr($value, 0, 1) === ':') {
428+
$instance = new UnquotedParameter();
429+
$instance->setName(substr($value, 1));
430+
} else {
431+
$instance = new LimitNode();
432+
$expr = $value;
433+
if (strpos($expr, "'") === 0) {
434+
$expr = substr($expr, 1);
435+
}
436+
if (strrpos($expr, "'") === strlen($expr) - 1) {
437+
$expr = substr($expr, 0, -1);
438+
}
439+
$expr = stripslashes($expr);
440+
441+
$instance->setValue($expr);
442+
}
443+
return $instance;
444+
}
445+
406446
private static function buildFromSubtree($subTree)
407447
{
408448
if ($subTree && is_array($subTree)) {

src/SQLParser/Node/Table.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,28 @@
4545
*/
4646
class Table implements NodeInterface
4747
{
48+
private $database;
49+
50+
/**
51+
* Returns the name of the database.
52+
*
53+
* @return mixed
54+
*/
55+
public function getDatabase()
56+
{
57+
return $this->database;
58+
}
59+
60+
/**
61+
* Sets the name of the database
62+
*
63+
* @param mixed $database
64+
*/
65+
public function setDatabase($database)
66+
{
67+
$this->database = $database;
68+
}
69+
4870
private $table;
4971

5072
/**
@@ -151,6 +173,7 @@ public function setRefClause($refClause)
151173
public function toInstanceDescriptor(MoufManager $moufManager)
152174
{
153175
$instanceDescriptor = $moufManager->createInstance(get_called_class());
176+
$instanceDescriptor->getProperty('database')->setValue($this->database);
154177
$instanceDescriptor->getProperty('table')->setValue($this->table);
155178
$instanceDescriptor->getProperty('alias')->setValue($this->alias);
156179
$instanceDescriptor->getProperty('joinType')->setValue($this->joinType);
@@ -175,6 +198,9 @@ public function toSql(array $parameters = array(), Connection $dbConnection = nu
175198
if ($this->refClause) {
176199
$sql .= "\n ".$this->joinType.' ';
177200
}
201+
if ($this->database) {
202+
$sql .= NodeFactory::escapeDBItem($this->database, $dbConnection).'.';
203+
}
178204
$sql .= NodeFactory::escapeDBItem($this->table, $dbConnection);
179205
if ($this->alias) {
180206
$sql .= ' AS '.NodeFactory::escapeDBItem($this->alias, $dbConnection);

src/SQLParser/Query/StatementFactory.php

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,22 @@ public static function toObject(array $desc)
9595
}
9696

9797
if (isset($desc['LIMIT'])) {
98-
$descLimit = self::checkLimitDesc($desc['LIMIT']);
98+
$descLimit = $desc['LIMIT'];
9999

100-
$limit = NodeFactory::toObject($descLimit['limit']);
100+
//$limit = NodeFactory::toObject($descLimit['limit']);
101101
//$limit = NodeFactory::simplify($limit);
102-
$select->setLimit($limit);
102+
if (isset($descLimit['rowcount'])) {
103+
$select->setLimit(NodeFactory::toLimitNode($descLimit['rowcount']));
104+
}
105+
106+
if (isset($descLimit['offset'])) {
107+
$select->setOffset(NodeFactory::toLimitNode($descLimit['offset']));
108+
}
103109

104-
$offset = NodeFactory::toObject($descLimit['offset']);
110+
111+
//$offset = NodeFactory::toObject($descLimit['offset']);
105112
//$offset = NodeFactory::simplify($offset);
106-
$select->setOffset($offset);
113+
//$select->setOffset($offset);
107114
}
108115

109116
return $select;
@@ -119,14 +126,14 @@ public static function toObject(array $desc)
119126
*
120127
* @throws \Exception
121128
*/
122-
private static function checkLimitDesc(array $descLimit)
129+
/*private static function checkLimitDesc(array $descLimit)
123130
{
124131
if (count($descLimit) > 2) {
125132
throw new \Exception('The limit returned by the SQLParser contains more than 2 items, something might went wrong.');
126133
}
127134
128-
return ['offset' => $descLimit[0], 'limit' => $descLimit[1]];
129-
}
135+
return ['offset' => $descLimit['offset'], 'limit' => $descLimit['rowcount']];
136+
}*/
130137

131138
/**
132139
* @param array $items An array of objects represented as SQLParser arrays.

tests/Mouf/Database/MagicQueryTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ public function testStandardSelect()
118118
$sql = 'SELECT \'hello\' as toto FROM users';
119119
$this->assertEquals('SELECT \'hello\' AS toto FROM users', self::simplifySql($magicQuery->build($sql)));
120120

121+
$sql = "SELECT Substring_index(ee.`data`, ':', -1) as foo FROM users";
122+
$this->assertEquals("SELECT Substring_index(ee.data, ':', -1) AS foo FROM users", self::simplifySql($magicQuery->build($sql)));
123+
121124
}
122125

123126
/**

0 commit comments

Comments
 (0)