Пример #1
0
 /**
  * {@inheritDoc}
  */
 public function open(array $data, Query\ReadSelection $selection)
 {
     $additional = $selection->getAdditionalFields();
     if (empty($additional)) {
         return RecordBuilder::open($this, $data, []);
     }
     $virtual = array();
     $subrecords = array();
     foreach ($data as $field => $value) {
         if (isset($additional[$field])) {
             if (isset($additional[$field]['record'])) {
                 $record = $additional[$field]['record'];
                 if (!isset($subrecords[$record])) {
                     $subrecords[$record] = ['model' => $additional[$field]['model'], 'null' => true, 'data' => []];
                 }
                 $subrecords[$record]['data'][$additional[$field]['recordField']] = $value;
                 if (isset($value)) {
                     $subrecords[$record]['null'] = false;
                 }
             } else {
                 $virtual[$field] = $value;
             }
             unset($data[$field]);
         }
     }
     foreach ($subrecords as $field => $record) {
         if ($record['null']) {
             $virtual[$field] = null;
         } else {
             $virtual[$field] = RecordBuilder::open($record['model'], $record['data']);
         }
     }
     return RecordBuilder::open($this, $data, $virtual);
 }
Пример #2
0
 /**
  * {@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);
 }
Пример #3
0
 /**
  * {@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;
 }
Пример #4
0
 /**
  * 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;
 }