Skip to content

Commit

Permalink
Improve Statement select process
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed May 23, 2024
1 parent 9e3df37 commit e201a39
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 37 deletions.
2 changes: 1 addition & 1 deletion src/Reader.php
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ public function matchingFirstOrFail(string $expression): TabularDataReader

public function select(string|int ...$columns): TabularDataReader
{
return Statement::create()->select(...$columns)->process($this);
return ResultSet::createFromTabularDataReader($this)->select(...$columns);
}

/**
Expand Down
56 changes: 52 additions & 4 deletions src/ResultSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,20 @@
use Closure;
use Generator;
use Iterator;
use IteratorIterator;
use JsonSerializable;
use League\Csv\Serializer\Denormalizer;
use League\Csv\Serializer\MappingFailed;
use League\Csv\Serializer\TypeCastingFailed;
use LimitIterator;
use Traversable;

use function array_filter;
use function array_flip;
use function array_key_exists;
use function array_reduce;
use function array_search;
use function array_values;
use function is_string;
use function iterator_count;

Expand Down Expand Up @@ -90,13 +95,17 @@ public static function createFromTabularDataReader(TabularDataReader $reader): s
}

/**
* Returns a new instance from a collection without header..
* Returns a new instance from a collection without header.
*
* @throws SyntaxError
*/
public static function createFromRecords(Iterator|array $records = []): self
public static function createFromRecords(iterable $records = []): self
{
return new self($records);
return new self(match (true) {
$records instanceof Iterator => $records,
$records instanceof Traversable => new IteratorIterator($records),
default => new ArrayIterator($records),
});
}

/**
Expand Down Expand Up @@ -218,7 +227,46 @@ public function sorted(Query\Sort|Closure $orderBy): TabularDataReader

public function select(string|int ...$columns): TabularDataReader
{
return Statement::create()->select(...$columns)->process($this);
if ([] === $columns) {
return $this;
}

$recordsHeader = $this->getHeader();
$hasHeader = [] !== $recordsHeader;
$selectColumn = function (array $header, string|int $field) use ($recordsHeader, $hasHeader): array {
if (is_string($field)) {
$index = array_search($field, $recordsHeader, true);
if (false === $index) {
throw InvalidArgument::dueToInvalidColumnIndex($field, 'offset', __METHOD__);
}

$header[$index] = $field;

return $header;
}

if ($hasHeader && !array_key_exists($field, $recordsHeader)) {
throw InvalidArgument::dueToInvalidColumnIndex($field, 'offset', __METHOD__);
}

$header[$field] = $recordsHeader[$field] ?? $field;

return $header;
};

/** @var array<string> $header */
$header = array_reduce($columns, $selectColumn, []);
$callback = function (array $record) use ($header): array {
$element = [];
$row = array_values($record);
foreach ($header as $offset => $headerName) {
$element[$headerName] = $row[$offset] ?? null;
}

return $element;
};

return new self(new MapIterator($this, $callback), $hasHeader ? $header : []);
}

public function matching(string $expression): iterable
Expand Down
40 changes: 8 additions & 32 deletions src/Statement.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,13 @@
use function array_reduce;
use function array_search;
use function array_values;
use function debug_backtrace;
use function end;
use function is_string;
use function func_num_args;
use function trigger_error;

use const DEBUG_BACKTRACE_IGNORE_ARGS;
use const E_USER_DEPRECATED;

/**
* Criteria to filter a {@link TabularDataReader} object.
*
* @phpstan-import-type ConditionExtended from \League\Csv\Query\PredicateCombinator
* @phpstan-import-type OrderingExtended from \League\Csv\Query\SortCombinator
* @phpstan-import-type ConditionExtended from Query\PredicateCombinator
* @phpstan-import-type OrderingExtended from Query\SortCombinator
*/
class Statement
{
Expand All @@ -64,11 +57,6 @@ class Statement
*/
public static function create(?callable $where = null, int $offset = 0, int $limit = -1): self
{
if (0 === func_num_args()) {
return new self();
}

self::triggerDeprecation('9.16.0', 'Using arguments with the `' . __METHOD__ . '` method is deprecated');
$stmt = new self();
if (null !== $where) {
$stmt = $stmt->where($where);
Expand All @@ -85,20 +73,6 @@ public static function create(?callable $where = null, int $offset = 0, int $lim
return $stmt;
}

private static function triggerDeprecation(string $version, string $message): void
{
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
$caller = end($backtrace);
if (isset($caller['file'])) {
$message .= '; called from ' . $caller['file'];
}
if (isset($caller['line'])) {
$message .= ' on line ' . $caller['line'];
}

@trigger_error('Since league\csv '.$version.': '.$message . '.', E_USER_DEPRECATED);
}

/**
* Sets the Iterator element columns.
*/
Expand Down Expand Up @@ -327,15 +301,17 @@ public function process(TabularDataReader $tabular_data, array $header = []): Ta
$iterator = Query\Limit::new($this->offset, $this->limit)->slice($iterator);
}

return match ($this->select) {
[] => new ResultSet($iterator, $header),
default => $this->applySelect($iterator, $header, $this->select),
};
return (new ResultSet($iterator, $header))->select(...$this->select);
}

/**
* DEPRECATION WARNING! This method will be removed in the next major point release.
*
* @throws InvalidArgument
*
* @throws SyntaxError
* @see Statement::process()
* @deprecated Since version 9.16.0
*/
protected function applySelect(Iterator $records, array $recordsHeader, array $select): TabularDataReader
{
Expand Down

0 comments on commit e201a39

Please sign in to comment.