diff --git a/src/SQLParser/Node/NodeFactory.php b/src/SQLParser/Node/NodeFactory.php index 6445788..8336370 100644 --- a/src/SQLParser/Node/NodeFactory.php +++ b/src/SQLParser/Node/NodeFactory.php @@ -452,19 +452,39 @@ private static function buildFromSubtree($subTree) if (!empty($subTree) && !isset($subTree[0])) { $subTree = StatementFactory::toObject($subTree); } else { - $subTree = array_map(function ($item) { - if (is_array($item)) { - return self::toObject($item); - } else { - return $item; - } - }, $subTree); + $subTree = self::mapArrayToNodeObjectList($subTree); } } return $subTree; } + /** + * @param array $items An array of objects represented as SQLParser arrays. + */ + public static function mapArrayToNodeObjectList(array $items) + { + $list = []; + + $nextAndPartOfBetween = false; + + // Special case, let's replace the AND of a between with a ANDBETWEEN object. + foreach ($items as $item) { + $obj = NodeFactory::toObject($item); + if ($obj instanceof Operator) { + if ($obj->getValue() == 'BETWEEN') { + $nextAndPartOfBetween = true; + } elseif ($nextAndPartOfBetween && $obj->getValue() == 'AND') { + $nextAndPartOfBetween = false; + $obj->setValue('AND_FROM_BETWEEN'); + } + } + $list[] = $obj; + } + + return $list; + } + private static $PRECEDENCE = array( array('INTERVAL'), array('BINARY', 'COLLATE'), diff --git a/src/SQLParser/Query/StatementFactory.php b/src/SQLParser/Query/StatementFactory.php index 52d687b..a3cb5ee 100644 --- a/src/SQLParser/Query/StatementFactory.php +++ b/src/SQLParser/Query/StatementFactory.php @@ -39,30 +39,30 @@ public static function toObject(array $desc) $select->setColumns($columns); if (isset($desc['FROM'])) { - $from = self::mapArrayToNodeObjectList($desc['FROM']); + $from = NodeFactory::mapArrayToNodeObjectList($desc['FROM']); $select->setFrom($from); } if (isset($desc['WHERE'])) { - $where = self::mapArrayToNodeObjectList($desc['WHERE']); + $where = NodeFactory::mapArrayToNodeObjectList($desc['WHERE']); $where = NodeFactory::simplify($where); $select->setWhere($where); } if (isset($desc['GROUP'])) { - $group = self::mapArrayToNodeObjectList($desc['GROUP']); + $group = NodeFactory::mapArrayToNodeObjectList($desc['GROUP']); $group = NodeFactory::simplify($group); $select->setGroup($group); } if (isset($desc['HAVING'])) { - $having = self::mapArrayToNodeObjectList($desc['HAVING']); + $having = NodeFactory::mapArrayToNodeObjectList($desc['HAVING']); $having = NodeFactory::simplify($having); $select->setHaving($having); } if (isset($desc['ORDER'])) { - $order = self::mapArrayToNodeObjectList($desc['ORDER']); + $order = NodeFactory::mapArrayToNodeObjectList($desc['ORDER']); $order = NodeFactory::simplify($order); $select->setOrder($order); } @@ -112,29 +112,4 @@ public static function toObject(array $desc) return ['offset' => $descLimit['offset'], 'limit' => $descLimit['rowcount']]; }*/ - /** - * @param array $items An array of objects represented as SQLParser arrays. - */ - private static function mapArrayToNodeObjectList(array $items) - { - $list = []; - - $nextAndPartOfBetween = false; - - // Special case, let's replace the AND of a between with a ANDBETWEEN object. - foreach ($items as $item) { - $obj = NodeFactory::toObject($item); - if ($obj instanceof Operator) { - if ($obj->getValue() == 'BETWEEN') { - $nextAndPartOfBetween = true; - } elseif ($nextAndPartOfBetween && $obj->getValue() == 'AND') { - $nextAndPartOfBetween = false; - $obj->setValue('AND_FROM_BETWEEN'); - } - } - $list[] = $obj; - } - - return $list; - } } diff --git a/tests/Mouf/Database/MagicQueryTest.php b/tests/Mouf/Database/MagicQueryTest.php index 8eb2597..84b23ca 100644 --- a/tests/Mouf/Database/MagicQueryTest.php +++ b/tests/Mouf/Database/MagicQueryTest.php @@ -78,6 +78,10 @@ public function testStandardSelect() $this->assertEquals("SELECT * FROM myTable WHERE someField <= '4'", self::simplifySql($magicQuery->build($sql, ['value2' => 4]))); $this->assertEquals('SELECT * FROM myTable', self::simplifySql($magicQuery->build($sql, []))); + $sql = 'SELECT * FROM myTable where (someField BETWEEN :value1 AND :value2) AND otherField = :value3'; + $this->assertEquals("SELECT * FROM myTable WHERE ((someField BETWEEN '2' AND '4')) AND (otherField = '8')", self::simplifySql($magicQuery->build($sql, ['value1' => 2, 'value2' => 4, 'value3' => 8]))); + + // Triggers an "expression" // TODO: find why it fails! //$sql = 'SELECT * FROM (users) WHERE name LIKE :name';