From b79ea12b449fcd2930133d77e220fd41a881f7e9 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Wed, 24 Sep 2014 16:18:36 +0300 Subject: [PATCH] query 2 --- application/Espo/ORM/DB/Mapper.php | 7 -- application/Espo/ORM/DB/Query.php | 68 +++++++++---- tests/Espo/ORM/DB/QueryTest.php | 158 +++++++++++++++++++++++++++++ 3 files changed, 209 insertions(+), 24 deletions(-) create mode 100644 tests/Espo/ORM/DB/QueryTest.php diff --git a/application/Espo/ORM/DB/Mapper.php b/application/Espo/ORM/DB/Mapper.php index d290b1da3a..a052918ae9 100644 --- a/application/Espo/ORM/DB/Mapper.php +++ b/application/Espo/ORM/DB/Mapper.php @@ -177,13 +177,6 @@ abstract class Mapper implements IMapper if (!$relEntity) { return null; } - - foreach (self::$selectParamList as $k) { - $$k = array_key_exists($k, $params) ? $params[$k] : null; - if (is_null($$k) && isset($relOpt[$k])) { - $$k = $relOpt[$k]; - } - } if ($totalCount) { $params['aggregation'] = 'COUNT'; diff --git a/application/Espo/ORM/DB/Query.php b/application/Espo/ORM/DB/Query.php index c7bfb9ae8a..e7fa9b9ed5 100644 --- a/application/Espo/ORM/DB/Query.php +++ b/application/Espo/ORM/DB/Query.php @@ -121,7 +121,14 @@ class Query $selectPart = $this->getAggregationSelect($entity, $params['aggregation'], $params['aggregationBy'], $aggDist); } - $joinsPart = $this->getBelongsToJoins($entity, $params['select']); + if (empty($params['joins'])) { + $params['joins'] = array(); + } + if (empty($params['leftJoins'])) { + $params['leftJoins'] = array(); + } + + $joinsPart = $this->getBelongsToJoins($entity, $params['select'], $params['joins'] + $params['leftJoins']); $wherePart = $this->getWhere($entity, $whereClause); @@ -169,13 +176,21 @@ class Query $select = ""; $arr = array(); $specifiedList = is_array($fields) ? true : false; - - foreach ($entity->fields as $field => $fieldDefs) { - if ($specifiedList) { + + if (empty($fields)) { + $fieldList = array_keys($entity->fields); + } else { + $fieldList = $fields; + } + + foreach ($fieldList as $field) { + $fieldDefs = $entity->fields[$field]; + + /*if ($specifiedList) { if (!in_array($field, $fields)) { continue; } - } + }*/ if (!empty($fieldDefs['select'])) { $fieldPath = $fieldDefs['select']; @@ -194,7 +209,25 @@ class Query return $select; } - protected function getBelongsToJoins(IEntity $entity, $select = null) + protected function getBelongsToJoin(IEntity $entity, $relationName, $r = null) + { + if (empty($r)) { + $r = $entity->relations[$relationName]; + } + + $keySet = $this->getKeys($entity, $relationName); + $key = $keySet['key']; + $foreignKey = $keySet['foreignKey']; + + $alias = $this->getAlias($entity, $relationName); + + if ($alias) { + return "JOIN `" . $this->toDb($r['entity']) . "` AS `" . $alias . "` ON ". + $this->toDb($entity->getEntityName()) . "." . $this->toDb($key) . " = " . $alias . "." . $this->toDb($foreignKey); + } + } + + protected function getBelongsToJoins(IEntity $entity, $select = null, $skipList = array()) { $joinsArr = array(); @@ -209,24 +242,21 @@ class Query } } - foreach ($entity->relations as $relationName => $r) { + foreach ($entity->relations as $relationName => $r) { if ($r['type'] == IEntity::BELONGS_TO) { + if (in_array($relationName, $skipList)) { + continue; + } + if (!empty($select)) { if (!in_array($relationName, $relationsToJoin)) { continue; } } - - $keySet = $this->getKeys($entity, $relationName); - $key = $keySet['key']; - $foreignKey = $keySet['foreignKey']; - $alias = $this->getAlias($entity, $relationName); - - if ($alias) { - $joinsArr[] = - "LEFT JOIN `" . $this->toDb($r['entity']) . "` AS `" . $alias . "` ON ". - $this->toDb($entity->getEntityName()) . "." . $this->toDb($key) . " = " . $alias . "." . $this->toDb($foreignKey); + $join = $this->getBelongsToJoin($entity, $relationName, $r); + if ($join) { + $joinsArr[] = 'LEFT ' . $join; } } } @@ -548,6 +578,10 @@ class Query return $join; } + + if ($relOpt['type'] == IEntity::BELONGS_TO) { + return $pre . $this->getBelongsToJoin($entity, $relationName); + } return false; } diff --git a/tests/Espo/ORM/DB/QueryTest.php b/tests/Espo/ORM/DB/QueryTest.php new file mode 100644 index 0000000000..726baf1351 --- /dev/null +++ b/tests/Espo/ORM/DB/QueryTest.php @@ -0,0 +1,158 @@ +pdo = $this->getMock('MockPDO'); + $this->pdo + ->expects($this->any()) + ->method('quote') + ->will($this->returnCallback(function() { + $args = func_get_args(); + return "'" . $args[0] . "'"; + })); + + + $this->entityFactory = $this->getMockBuilder('\\Espo\\ORM\\EntityFactory')->disableOriginalConstructor()->getMock(); + $this->entityFactory->expects($this->any()) + ->method('create') + ->will($this->returnCallback(function() { + $args = func_get_args(); + $className = "\\Espo\\Entities\\" . $args[0]; + return new $className(); + })); + + $this->query = new Query($this->pdo, $this->entityFactory); + + $this->post = new \Espo\Entities\Post(); + $this->comment = new \Espo\Entities\Comment(); + $this->tag = new \Espo\Entities\Tag(); + $this->note = new \Espo\Entities\Note(); + + $this->contact = new \Espo\Entities\Contact(); + $this->account = new \Espo\Entities\Account(); + } + + protected function tearDown() + { + unset($this->query); + unset($this->pdo); + unset($this->post); + unset($this->tag); + unset($this->note); + unset($this->contact); + unset($this->account); + } + + public function testSelectAllColumns() + { + $sql = $this->query->createSelectQuery('Account', array( + 'orderBy' => 'name', + 'order' => 'ASC', + 'offset' => 10, + 'limit' => 20 + )); + + $expectedSql = + "SELECT account.id AS `id`, account.name AS `name`, account.deleted AS `deleted` FROM `account` " . + "WHERE account.deleted = '0' ORDER BY account.name ASC LIMIT 10, 20"; + + $this->assertEquals($sql, $expectedSql); + } + + public function testSelectWithBelongsToJoin() + { + $sql = $this->query->createSelectQuery('Comment', array( + + )); + + $expectedSql = + "SELECT comment.id AS `id`, comment.post_id AS `postId`, post.name AS `postName`, comment.name AS `name`, comment.deleted AS `deleted` FROM `comment` " . + "LEFT JOIN `post` AS `post` ON comment.post_id = post.id " . + "WHERE comment.deleted = '0'"; + + $this->assertEquals($sql, $expectedSql); + } + + public function testSelectWithSpecifiedColumns() + { + $sql = $this->query->createSelectQuery('Comment', array( + 'select' => array('id', 'name') + )); + $expectedSql = + "SELECT comment.id AS `id`, comment.name AS `name` FROM `comment` " . + "WHERE comment.deleted = '0'"; + + $this->assertEquals($sql, $expectedSql); + + $sql = $this->query->createSelectQuery('Comment', array( + 'select' => array('id', 'name', 'postName') + )); + $expectedSql = + "SELECT comment.id AS `id`, comment.name AS `name`, post.name AS `postName` FROM `comment` " . + "LEFT JOIN `post` AS `post` ON comment.post_id = post.id " . + "WHERE comment.deleted = '0'"; + + $this->assertEquals($sql, $expectedSql); + + $sql = $this->query->createSelectQuery('Comment', array( + 'select' => array('id', 'name', 'postName'), + 'leftJoins' => array('post') + )); + $expectedSql = + "SELECT comment.id AS `id`, comment.name AS `name`, post.name AS `postName` FROM `comment` " . + "LEFT JOIN `post` AS `post` ON comment.post_id = post.id " . + "WHERE comment.deleted = '0'"; + + $this->assertEquals($sql, $expectedSql); + + $sql = $this->query->createSelectQuery('Comment', array( + 'select' => array('id', 'name'), + 'leftJoins' => array('post') + )); + $expectedSql = + "SELECT comment.id AS `id`, comment.name AS `name` FROM `comment` " . + "LEFT JOIN `post` AS `post` ON comment.post_id = post.id " . + "WHERE comment.deleted = '0'"; + + $this->assertEquals($sql, $expectedSql); + } + + /*public function testSelectWithSpecifiedFunction() + { + $sql = $this->query->createSelectQuery('Comment', array( + 'select' => array('id', 'name', 'postId', 'COUNT:id'), + 'leftJoins' => array('post'), + 'groupBy' => array('postId', 'post.name') + )); + $expectedSql = + "SELECT comment.id AS `id`, comment.post_id AS `postId`, comment.name AS `name`, COUNT(id) AS `COUNT:id` FROM `comment` " . + "LEFT JOIN `post` AS `post` ON comment.post_id = post.id " . + "WHERE comment.deleted = '0' " . + "GROUP BY comment.post_id, post.name"; + + $this->assertEquals($sql, $expectedSql); + }*/ + +} + +