问题
My Atlas
class performs a recursive data exploration given a non-contiguous but sequential set of col1
values, read from MySQL table1
beginning with $startingVal
. Limit $totalVal
is a throttle for work units during any given session. On each recursion, Atlas
will retrieve between zero and eight (0-8) rows from a different table.
Fatal error: Uncaught exception 'Zend\Db\Adapter\Exception\RuntimeException'
with message 'Row count is not available in unbuffered result sets.'
in /path/vendor/Zend/zend-db/src/Adapter/Driver/Mysqli/Result.php:316
Stack trace:
#0 /path/vendor/Zend/zend-db/src/ResultSet/AbstractResultSet.php(65):
Zend\Db\Adapter\Driver\Mysqli\Result->count()
#1 /path/vendor/Zend/zend-db/src/Adapter/Adapter.php(195):
Zend\Db\ResultSet\AbstractResultSet->
initialize(Object(Zend\Db\Adapter\Driver\Mysqli\Result))
#2 /path/modules/Flightplan/src/Flightplan/Atlas.php(110): Zend\Db\Adapter\Adapter->query('SELECT col1...', Array)
#3 /path/utility.php(46):
Flightplan\Atlas->shoulder_routes('30000001', '1')
#4 {main} thrown in /path/vendor/Zend/zend-db/src/Adapter/Driver/Mysqli/Result.php
on line 316
If I am reading the error and Zend source correctly, Adapter
is initializing an AbstractResultSet
(buffering by default) with a Mysqli\Result
resource (non buffering by default), and immediately after, tries to count it, which throws the error. This is happening the during my first query through Adapter, before recursion.
AbstractResultSet.php
public function initialize($dataSource)
{
// reset buffering
if (is_array($this->buffer)) {
$this->buffer = array();
}
if ($dataSource instanceof ResultInterface) {
$this->count = $dataSource->count(); // line 65
Atlas.php:
use Zend\Db\Adapter\Adapter;
public function __construct( array $configArray = null ){
...
$this->configArray = $configArray;
$this->adapter = new Adapter( $this->configArray );
}
public function shoulder_routes( $startingVal, $totalVal ){
...
$result = $this->adapter->query( 'SELECT col1 FROM table1
WHERE col1 >= ? LIMIT ?', array( $startingVal, $totalVal )); // line 110
$result->buffer(); // ADDED AFTER 1st error occurrence
...
}
I added $result->buffer();
which is unfortunately useless since the error occurs before execution returns to Atlas
.
How can I rectify this?
Mysqli\Result
CAN be set to buffer at initialization. Do I extendResult
with buffering on by default, and would I specify that inAtlas
, like:
$this->adapter = new Adapter( $this->configArray,null,new MyMysqliResult() );
Edit: Supplying a ResultInterface as a parameter to Adapter threw an error, as Adapter is expecting a ResultSet. However, it may be possible to extend AbstractResultSet so that IT calls $result->buffer() before calling $result->count() on the ResultSet passed to it from Adaper\Driver\Mysqli...
- (I think) I read that Zend\Adapter PDO_Mysql driver/platform/result DOES buffer by default. Is there any reason not to switch to PDO?
Edit: Switching to PDO_Mysql Adapter\Driver resulted in following error, which I imagine may be resolved if I prepare a driver-supplied statement
Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'' at line 1' in /path/vendor/Zend/zend-db/src/Adapter/Driver/Pdo/Statement.php:239
- I have also seen in this answer where
result->getResource()->fetchAll();
may help later inAtlas
but again the error is occurring before I get this chance.
What am I missing? Thanks -
回答1:
After coming and going from this problem and project for a few months, I stumbled upon an answer here which lead me to the same answer here.
$config => array(
...
'options' => array(
'buffer_results' => true,
),
I was looking for this kind of answer, and obviously stared too hard.
来源:https://stackoverflow.com/questions/42243287/how-can-i-buffer-an-unbuffered-resultset-in-zf2-zend-db