/** * {@inheritdoc} */ public function read(ReadSelection $selection) { $data = $this->getData(); if (count($selection->getJoins()) > 0) { throw new \Exception('unsupported operation'); } $predicate = $selection->getPredicate(); $data = new PredicateArray($data, $predicate); $grouping = $selection->getGrouping(); if (count($grouping)) { $data = self::sortAll($data, $grouping); $predicate = $selection->getGroupPredicate(); if (isset($predicate)) { $data = new PredicateArray($data, $predicate); } } $data = self::sortAll($data, $selection->getOrdering()); $limit = $selection->getLimit(); $offset = $selection->getOffset(); if (isset($limit)) { $data = array_slice($data, $offset, $limit); } // TODO: implement projection return $data; }
/** * {@inheritdoc} */ public function readSelection(ReadSelection $selection) { // TODO: distinct and additionalFields $data = $this->getData(); if (count($selection->getJoins()) > 0) { throw new \Exception('unsupported operation'); } $predicate = $selection->getPredicate(); if (isset($predicate)) { $data = new PredicateArray($data, $predicate); } $grouping = $selection->getGrouping(); if (count($grouping)) { $data = self::sortAll($data, array_map(function ($column) { return [$column, false]; }, $grouping)); $previous = null; $data = array_filter($data, function ($record) use($grouping, &$previous) { $group = array_intersect_key($record, array_flip($grouping)); if (isset($previous) and $group == $previous) { return false; } $previous = $group; return true; }); $predicate = $selection->getGroupPredicate(); if (isset($predicate)) { $data = new PredicateArray($data, $predicate); } } $data = self::sortAll($data, $selection->getOrdering()); $limit = $selection->getLimit(); $offset = $selection->getOffset(); if (isset($limit)) { $data = array_slice($data, $offset, $limit); } $projection = $selection->getProjection(); if (count($projection)) { $projected = array(); foreach ($data as $key => $record) { $recordData = array(); $i = 0; foreach ($projection as $field) { if (isset($field['alias'])) { $alias = $field['alias']; } else { $alias = 'expr#' . $i++; } $recordData[$alias] = $field['expression']->__invoke($record); } $projected[] = $recordData; } $data = $projected; } if ($data instanceof \Iterator) { return $data; } return new \ArrayIterator($data); }
/** * Convert a read selection to an SQL query. * * @param ReadSelectionBuilder $selection * Read selection. * @param string|null $projection * Projection override. * @return string SQL query. */ private function convertReadSelection(ReadSelection $selection, $projection = null) { $sqlString = 'SELECT '; $alias = $selection->getAlias(); if ($selection->isDistinct()) { $sqlString .= 'DISTINCT '; } if (isset($projection)) { $sqlString .= $projection; } elseif (count($selection->getProjection())) { $fields = $selection->getProjection(); array_walk($fields, array($this, 'getColumnList')); $sqlString .= implode(', ', $fields); } else { if (isset($alias)) { $sqlString .= $alias . '.*'; } else { $sqlString .= $this->owner->quoteModel($this->name) . '.*'; } $additional = $selection->getAdditionalFields(); if (count($additional)) { array_walk($additional, array($this, 'getColumnList')); $sqlString .= ', ' . implode(', ', $additional); } } $sqlString .= ' FROM ' . $this->owner->quoteModel($this->name); if (isset($alias)) { $sqlString .= ' AS ' . $alias; } // if (!empty($selection->sources)) { // foreach ($selection->sources as $source) { // if (is_string($source['source'])) { // $table = $source['source']; // } elseif ($source['source'] instanceof SqlTable) { // $table = $source['source']->name; // } else { // continue; // } // $sqlString .= ', ' . $this->owner->quoteModel($table); // if (isset($source['alias'])) { // $sqlString .= ' AS ' . $source['alias']; // } // } // } $joins = $selection->getJoins(); if (count($joins)) { foreach ($joins as $join) { $joinSource = $join['source']->joinWith($this); if (!isset($joinSource)) { throw new InvalidTableException('Unable to join SqlTable with data source of type "' . get_class($join['source']) . '"'); } if ($joinSource->owner !== $this->owner) { throw new InvalidTableException('Unable to join SqlTable with table of different database'); } $table = $joinSource->name; $sqlString .= ' ' . $join['type'] . ' JOIN ' . $this->owner->quoteModel($table); if (isset($join['alias'])) { $sqlString .= ' AS ' . $join['alias']; } if (isset($join['condition'])) { $sqlString .= ' ON ' . $join['condition']->toString($this->owner); } } } if ($selection->getPredicate() !== null) { $sqlString .= ' WHERE ' . $selection->getPredicate()->toString($this->owner); } $grouping = $selection->getGrouping(); if (count($grouping)) { $columns = array(); foreach ($grouping as $column) { $columns[] = $this->escapeQuery($column); } $sqlString .= ' GROUP BY ' . implode(', ', $columns); $predicate = $selection->getGroupPredicate(); if (isset($predicate)) { $sqlString .= ' HAVING ' . $predicate->toString($this->owner); } } $ordering = $selection->getOrdering(); if (count($ordering)) { $columns = array(); foreach ($ordering as $orderBy) { $columns[] = $this->escapeQuery($orderBy[0]) . ($orderBy[1] ? ' DESC' : ' ASC'); } $sqlString .= ' ORDER BY ' . implode(', ', $columns); } $limit = $selection->getLimit(); if (isset($limit)) { $sqlString .= ' ' . $this->owner->sqlLimitOffset($limit, $selection->getOffset()); } return $sqlString; }