Git Product home page Git Product logo

Comments (13)

dmjohnsson23 avatar dmjohnsson23 commented on August 11, 2024

I spent some time digging into the source myself so see if I could isolate the problem, and arrived at this minimal example that reproduces the issues:

<?php
require_once 'inc/prelude.php';
use loophp\iterators\ClosureIteratorAggregate;
use loophp\collection\Iterator\PsrCacheIterator;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use loophp\iterators\FilterIterableAggregate;
$fromDate = '2023-09-15 00:00:00';
$toDate = '2023-09-30 23:59:59';
$query = "SELECT *
          FROM communication
          WHERE `date` BETWEEN :fromDate AND :toDate";
$statement = $pdo->prepare($query);
$statement->bindValue('fromDate', $fromDate, PDO::PARAM_STR);
$statement->bindValue('toDate', $toDate, PDO::PARAM_STR);
$statement->execute();
$statement->setFetchMode(PDO::FETCH_ASSOC);
echo $statement->rowCount();
$cached = new ClosureIteratorAggregate(fn () => yield from new PsrCacheIterator($statement->getIterator(), new ArrayAdapter()), []);
$get = fn () => yield from new FilterIterableAggregate($cached, fn()=>true);
$get()->current();
$get()->current();

foreach ($cached as $i=> $r){
    var_dump($i, $r);
}

However, "unwapping" the ClosureIteratorAggregate seems to solve the issue. This code produces the expected results:

<?php
require_once 'inc/prelude.php';
use loophp\iterators\ClosureIteratorAggregate;
use loophp\collection\Iterator\PsrCacheIterator;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use loophp\iterators\FilterIterableAggregate;
$fromDate = '2023-09-15 00:00:00';
$toDate = '2023-09-30 23:59:59';
$query = "SELECT *
          FROM communication
          WHERE `date` BETWEEN :fromDate AND :toDate";
$statement = $pdo->prepare($query);
$statement->bindValue('fromDate', $fromDate, PDO::PARAM_STR);
$statement->bindValue('toDate', $toDate, PDO::PARAM_STR);
$statement->execute();
$statement->setFetchMode(PDO::FETCH_ASSOC);
echo $statement->rowCount();
$cached = new PsrCacheIterator($statement->getIterator(), new ArrayAdapter());
$get = fn () => yield from new FilterIterableAggregate($cached, fn()=>true);
$get()->current();
$get()->current();

foreach ($cached as $i=> $r){
    var_dump($i, $r);
}

Therefore the issue may actually be in the dependency loophp\iterators.

from collection.

github-actions avatar github-actions commented on August 11, 2024

Since this issue has not had any activity within the last 5 days, I have marked it as stale.
I will close it if no further activity occurs within the next 5 days.

from collection.

drupol avatar drupol commented on August 11, 2024

Hello,

I apologize for the delayed response; my schedule has been quite packed lately. Thank you for your patience.

Were you able to find a solution to the issue in the meantime?

from collection.

dmjohnsson23 avatar dmjohnsson23 commented on August 11, 2024

No worries, it's not a sin to have a life outside of Github. Take the time you need with what is important to you.

I was able to work around the issue by using fetchAll to convert the iterable to an array before turning it into a Collection. Not being able to use cache in unfortunate, but it isn't a show-stopper.

However, I never did manage to identify the root cause of the issue or create an actual fix. I suspect that somewhere along the chain of iteratables there is one that isn't fully abstracting over the previous one in the chain, but I spent several hours looking and couldn't find it.

from collection.

drupol avatar drupol commented on August 11, 2024

I have to admit that I wish I could reproduce this easily at home, but I don't have any project using Doctrine right now, so I don't know how to do this.

Do you have a way to reproduce this easily with a SQLite based project, for example? So we could share a project and reproduce the issue?

from collection.

dmjohnsson23 avatar dmjohnsson23 commented on August 11, 2024

I'm actually not using Doctrine either, I'm using PDO.

Sure, here is a complete, self-contained script that reproduces the issue using SQLite:

<?php require_once 'vendor/autoload.php';
use loophp\iterators\ClosureIteratorAggregate;
use loophp\collection\Iterator\PsrCacheIterator;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use loophp\iterators\FilterIterableAggregate;

$pdo = new PDO('sqlite::memory:');
$pdo->query("CREATE TABLE communication(
    id INTEGER PRIMARY KEY,
    date TEXT,
    remarks TEXT
);");
$pdo->query("INSERT INTO communication
    (id, date, remarks)
    VALUES
    (1, '2023-09-17 11:47:11', 'This is the first one'),
    (2, '2023-09-18 07:52:19', 'This is the second one'),
    (3, '2023-09-19 13:05:17', 'This is the third one');
");


$fromDate = '2023-09-15 00:00:00';
$toDate = '2023-09-30 23:59:59';
$query = "SELECT *
          FROM communication
          WHERE `date` BETWEEN :fromDate AND :toDate";
$statement = $pdo->prepare($query);
$statement->bindValue('fromDate', $fromDate, PDO::PARAM_STR);
$statement->bindValue('toDate', $toDate, PDO::PARAM_STR);
$statement->execute();
$statement->setFetchMode(PDO::FETCH_ASSOC);

$cached = new ClosureIteratorAggregate(fn () => yield from new PsrCacheIterator($statement->getIterator(), new ArrayAdapter()), []);
$get = fn () => yield from new FilterIterableAggregate($cached, fn()=>true);
$get()->current();
$get()->current();

foreach ($cached as $i=> $r){
    var_dump($i, $r);
}

Actual output:

int(0)
array(3) {
  ["id"]=>
  int(3)
  ["date"]=>
  string(19) "2023-09-19 13:05:17"
  ["remarks"]=>
  string(21) "This is the third one"
}

Expected output:

int(0)
array(3) {
  ["id"]=>
  int(1)
  ["date"]=>
  string(19) "2023-09-17 11:47:11"
  ["remarks"]=>
  string(21) "This is the first one"
}
int(1)
array(3) {
  ["id"]=>
  int(2)
  ["date"]=>
  string(19) "2023-09-18 07:52:19"
  ["remarks"]=>
  string(22) "This is the second one"
}
int(2)
array(3) {
  ["id"]=>
  int(3)
  ["date"]=>
  string(19) "2023-09-19 13:05:17"
  ["remarks"]=>
  string(21) "This is the third one"
}

from collection.

drupol avatar drupol commented on August 11, 2024

Thanks for the snippet.

I modified it a bit:

<?php declare(strict_types=1);

namespace Bug;

use loophp\collection\Collection;
use PDO;

require_once __DIR__ . '/vendor/autoload.php';

$pdo = new PDO('sqlite::memory:');
$pdo->query("CREATE TABLE communication(
    id INTEGER PRIMARY KEY,
    date TEXT,
    remarks TEXT
);");
$pdo->query("INSERT INTO communication
    (id, date, remarks)
    VALUES
    (1, '2023-09-17 11:47:11', 'This is the first one'),
    (2, '2023-09-18 07:52:19', 'This is the second one'),
    (3, '2023-09-19 13:05:17', 'This is the third one');
");

$fromDate = '2023-09-15 00:00:00';
$toDate = '2023-09-30 23:59:59';
$query = "SELECT *
          FROM communication
          WHERE `date` BETWEEN :fromDate AND :toDate";
$statement = $pdo->prepare($query);
$statement->bindValue('fromDate', $fromDate, PDO::PARAM_STR);
$statement->bindValue('toDate', $toDate, PDO::PARAM_STR);
$statement->execute();
$statement->setFetchMode(PDO::FETCH_ASSOC);

$collection = Collection::fromIterable($statement->getIterator());

$collection->current();
$collection->current();

foreach ($collection as $i => $r){
    var_dump($i, $r);
}

And the bug seems to be gone.

Is it working on your side?

from collection.

dmjohnsson23 avatar dmjohnsson23 commented on August 11, 2024

Yes, that code seem to give the expected result. I played around with it a little, and the change that seems to make the difference is using $statement->getIterator() rather than just $statement. It's interesting to me, since PDOStatement implements IteratorAggregate, so I would generally consider it to be iterable all by itself. Now I'm really curious why that makes a difference.

from collection.

drupol avatar drupol commented on August 11, 2024

I have the feeling that it is something internal... maybe it would be nice to reproduce the issue without using any libraries and submit it upstream.

from collection.

dmjohnsson23 avatar dmjohnsson23 commented on August 11, 2024

I'm beginning to wonder the same thing; the bug may be with PDO or PHP itself.

from collection.

drupol avatar drupol commented on August 11, 2024

I'll do further tests tomorrow. In any case, nice catch :)

from collection.

github-actions avatar github-actions commented on August 11, 2024

Since this issue has not had any activity within the last 5 days, I have marked it as stale.
I will close it if no further activity occurs within the next 5 days.

from collection.

drupol avatar drupol commented on August 11, 2024

@dmjohnsson23 The issue now closed, let me know if you need more assistance or eventually if you find more information about this issue.
Feel free to reopen it in any case.

from collection.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.