6

Ok, so we've got a new server with

  • Debian Wheezy 32BIT
  • PHP 5.5.18
  • FreeTDS 0.91

This PHP app needs to talk to an old SQL server 2000 server. We used the old code from our previous server (PHP 5.2 and older FreeTDS - can't get the version). We connect to SQL server 2000 through PDO using dblib driver.

We're experiencing weird behaviour with the fetch function. Basically if we issue a query during a fetch loop on the same pdo connection object, the main query gets reset and next fetch call will return false even if there are still records to be fetched.

// PSEUDO CODE
// Here the main query
$q = $sql7->query("SELECT TOP 5 * FROM News ORDER BY Data Desc");
while ($row = $q->fetch(PDO::FETCH_ASSOC)) {
    // Looping through the results
    echo "<h1>Main query</h1>";
    print_r($row);

    // Issue a query on the same pdo connection
    $subq = $sql7->query("SELECT TOP 1 * FROM News WHERE IDNews = " . $row['IDNews'] . " ");
    while ($subResult = $subq->fetch(PDO::FETCH_ASSOC)) {
        echo "<h1>Inner query</h1>";
        print_r($subResult);
    }

    // Here the main query $q->fetch(PDO::FETCH_ASSOC) will answer false on the next iteration
    // if we remove the subq, the main query loops just fine
    echo "<hr>";
}

Same code on a Windows PHP with pdo_sqlserver driver works just fine.

It doesn't matter the type of fetch that we pass as argument of fetch function.

PHP doesn't throw any warning or error.

I really don't know what's going on here.

S.Magnaschi
  • 787
  • 5
  • 12
  • 1
    Not sure that PDO does 'nested' queries very well. I suggest a 'fetchAll' on the 'outer' query. This may be useful: [#65945 Nested use of pdo->prepare()->execute clears the outer resultset-object](https://bugs.php.net/bug.php?id=65945). – Ryan Vincent Nov 12 '14 at 12:50
  • Thanks Ryan, it seems that the link you provided says it all. Thanks! :) – S.Magnaschi Nov 12 '14 at 14:54

1 Answers1

4

As of: reference (PHP BUG SITE)

This is the behavior of MSSQL (TDS), DBLIB and FreeTDS. One statement per connection rule. If you initiate another statement, the previous statement is cancelled.

The previous versions buffered the entire result set in memory leading to OOM errors on large results sets.

So, it seems that it was the previous versions of PHP (5.3 and previous) that were not conforming to the TDS behaviour. We need to refactor the code then.

S.Magnaschi
  • 787
  • 5
  • 12
  • 2
    Be aware: sqlsrv used on Windows will have the previous behaviour. So take care of this if you develop on your Windows machine but production server is Linux – Marco Marsala Jun 08 '15 at 14:12
  • @MarcoMarsala do you know the behaviour of the PDO_ODBC driver on MS SQL Server? – Eugenio Oct 23 '18 at 18:52
  • I confirm that pdo_sqlsrv has the same behaviour also on *nix (at least on MacOS, php 7.1.1): fetching recordsets of "nested" queries (differently from pdo_dblib) doesn't affect previous (still not completely fetched) recordsets. – Eugenio Oct 26 '18 at 11:29