support des colonnes

This commit is contained in:
Jephté Clain 2025-03-04 06:53:19 +04:00
parent 2812046b4b
commit 1a5ca79ef7
2 changed files with 79 additions and 14 deletions

View File

@ -2,6 +2,7 @@
namespace nur\sery\wip\php\coll;
use Iterator;
use IteratorAggregate;
use nulib\cl;
use nulib\php\func;
use nur\sery\wip\php\iter;
@ -33,7 +34,7 @@ class Cursor implements Iterator {
* alors retourner le tableau
* ["a" => $row["a"], "b" => $row["x"], "c" => "y", "d" => null]
*/
private static function map_row(array $row, ?array $map): array {
protected static function map_row(array $row, ?array $map): array {
if ($map === null) return $row;
$index = 0;
$mapped = [];
@ -48,7 +49,7 @@ class Cursor implements Iterator {
$mapped[$key] = $func->invoke([$value, $key, $row]);
} else {
if ($value === null) $mapped[$key] = null;
else $mapped[$key] = cl::get($row, $key);
else $mapped[$key] = cl::get($row, $value);
}
}
return $mapped;
@ -67,7 +68,7 @@ class Cursor implements Iterator {
* - une valeur associative $key => $value indique que la clé correspondante
* doit exiter avec la valeur spécifiée
*/
private static function filter_row(array $row, $filter): bool {
protected static function filter_row(array $row, $filter): bool {
if ($filter === null) return false;
if (!is_array($filter)) $filter = [$filter];
if (!$filter) return false;
@ -79,12 +80,12 @@ class Cursor implements Iterator {
if (!array_key_exists($value, $row)) return false;
} elseif (is_bool($value)) {
if ($value) {
if (!array_key_exists($value, $row)) return false;
if (!array_key_exists($key, $row)) return false;
} else {
if (array_key_exists($value, $row)) return false;
if (array_key_exists($key, $row)) return false;
}
} else {
if (!array_key_exists($value, $row)) return false;
if (!array_key_exists($key, $row)) return false;
if ($row[$key] !== $value) return false;
}
}
@ -114,6 +115,11 @@ class Cursor implements Iterator {
$this->rowsGenerator = $rowsGenerator;
$this->rowsFunc = $rowsFunc;
$this->cols = $params["cols"] ?? null;
$colsFunc = $params["cols_func"] ?? null;
if ($colsFunc !== null) $colsFunc = func::with($colsFunc);
$this->colsFunc = $colsFunc;
$map = $params["map"] ?? null;
$mapFunc = $params["map_func"] ?? null;
if ($mapFunc !== null) {
@ -140,16 +146,16 @@ class Cursor implements Iterator {
/** un générateur de lignes */
private ?Traversable $rowsGenerator;
/** une fonction de signature <code>function(Cursor):?iterable</code> */
/** une fonction de signature <code>function(Cursor): ?iterable</code> */
private ?func $rowsFunc;
/** une fonction de signature <code>function(Cursor):?array</code> */
/** une fonction de signature <code>function(Cursor): ?array</code> */
private ?func $colsFunc;
/** une fonction de signature <code>function(Cursor):?array</code> */
/** une fonction de signature <code>function(Cursor): ?array</code> */
private ?func $mapFunc;
/** une fonction de signature <code>function(Cursor):bool</code> */
/** une fonction de signature <code>function(Cursor): bool</code> */
private ?func $filterFunc;
protected ?iterable $rows;
@ -173,6 +179,10 @@ class Cursor implements Iterator {
return null;
}
protected function cols(): ?array {
return $this->row !== null? array_keys($this->row): null;
}
protected function filter(): bool {
return false;
}
@ -185,20 +195,24 @@ class Cursor implements Iterator {
# Iterator
function rewind() {
$this->cols = null;
$this->index = 0;
$this->origIndex = 0;
$this->key = null;
$this->raw = null;
$this->row = null;
if ($this->rowsGenerator !== null) {
$this->rows = $this->rowsGenerator;
$this->rows->rewind();
$rows = $this->rowsGenerator;
if ($rows instanceof IteratorAggregate) $rows = $rows->getIterator();
$rows->rewind();
$this->rows = $rows;
} else {
$this->rows = $this->rowsFunc->invoke();
}
}
function valid() {
function valid(): bool {
$cols = $this->colsFunc;
$filter = $this->filterFunc;
$map = $this->mapFunc;
while ($valid = iter::valid($this->rows)) {
@ -210,6 +224,10 @@ class Cursor implements Iterator {
if (!$filtered) {
if ($map === null) $this->row = $this->map();
else $this->row = $map->invoke([$this]);
if ($this->cols === null) {
if ($cols === null) $this->cols = $this->cols();
else $this->cols = $cols->invoke([$this]);
}
break;
} else {
iter::next($this->rows);
@ -219,6 +237,7 @@ class Cursor implements Iterator {
if (!$valid) {
iter::close($this->rows);
$this->rows = null;
$this->cols = null;
$this->index = -1;
$this->origIndex = -1;
$this->key = null;
@ -228,7 +247,7 @@ class Cursor implements Iterator {
return $valid;
}
function current() {
function current(): ?array {
return $this->row;
}

View File

@ -13,6 +13,43 @@ class CursorTest extends TestCase {
msg::set_messenger(new StdMessenger());
}
function test_map_row() {
$cursor = new class extends Cursor {
function mapRow(array $row, ?array $map): array {
return self::map_row($row, $map);
}
};
$row = ["a" => 1, "b" => 2, "c" => 3, "x" => 99];
$map = ["a", "b" => "x", "c" => function() { return "y"; }, "d" => null];
self::assertSame([
"a" => $row["a"],
"b" => $row["x"],
"c" => "y",
"d" => null
], $cursor->mapRow($row, $map));
}
function test_filter_row() {
$cursor = new class extends Cursor {
function filterRow(array $row, $filter): bool {
return self::filter_row($row, $filter);
}
};
$row = ["a" => 1, "b" => 2, "c" => 3, "x" => 99];
self::assertTrue($cursor->filterRow($row, "a"));
self::assertTrue($cursor->filterRow($row, ["a"]));
self::assertTrue($cursor->filterRow($row, ["a" => true]));
self::assertFalse($cursor->filterRow($row, ["a" => false]));
self::assertTrue($cursor->filterRow($row, ["a" => 1]));
self::assertFalse($cursor->filterRow($row, ["a" => 2]));
self::assertFalse($cursor->filterRow($row, "z"));
self::assertFalse($cursor->filterRow($row, ["z"]));
self::assertFalse($cursor->filterRow($row, ["z" => true]));
self::assertTrue($cursor->filterRow($row, ["z" => false]));
self::assertFalse($cursor->filterRow($row, ["z" => 1]));
}
const SCALARS = [0, 1, 2, 3, 4];
function generator() {
@ -41,6 +78,15 @@ class CursorTest extends TestCase {
return cl::all($c);
});
$c = new Cursor(null, [
"rows" => $this->generator(),
]);
self::assertSame([[0], [1], [2], [3], [4]], cl::all($c));
self::assertException(Exception::class, function() use ($c) {
// pas possible de rewind un générateur
return cl::all($c);
});
$c = new Cursor(null, [
"rows_func" => function() {
return self::SCALARS;