silverstripe-framework/ORM/Connect/MySQLStatement.php

123 lines
2.5 KiB
PHP

<?php
namespace SilverStripe\ORM\Connect;
/**
* Provides a record-view for mysqli statements
*
* By default streams unbuffered data, but seek(), rewind(), or numRecords() will force the statement to
* buffer itself and sacrifice any potential performance benefit.
*
* @package framework
* @subpackage orm
*/
class MySQLStatement extends SS_Query {
/**
* The related mysqli statement object if generated using a prepared query
*
* @var mysqli_stmt
*/
protected $statement;
/**
* Metadata result for this statement
*
* @var mysqli_result
*/
protected $metadata;
/**
* Is the statement bound to the current resultset?
*
* @var bool
*/
protected $bound = false;
/**
* List of column names
*
* @var array
*/
protected $columns = array();
/**
* List of bound variables in the current row
*
* @var array
*/
protected $boundValues = array();
/**
* Binds this statement to the variables
*/
protected function bind() {
$variables = array();
// Bind each field
while($field = $this->metadata->fetch_field()) {
$this->columns[] = $field->name;
// Note that while boundValues isn't initialised at this point,
// later calls to $this->statement->fetch() Will populate
// $this->boundValues later with the next result.
$variables[] = &$this->boundValues[$field->name];
}
$this->bound = true;
$this->metadata->free();
// Buffer all results
$this->statement->store_result();
call_user_func_array(array($this->statement, 'bind_result'), $variables);
}
/**
* Hook the result-set given into a Query class, suitable for use by SilverStripe.
* @param mysqli_stmt $statement The related statement, if present
* @param mysqli_result $metadata The metadata for this statement
*/
public function __construct($statement, $metadata) {
$this->statement = $statement;
$this->metadata = $metadata;
// Immediately bind and buffer
$this->bind();
}
public function __destruct() {
$this->statement->close();
$this->closed = true;
$this->currentRecord = false;
}
public function seek($row) {
$this->rowNum = $row - 1;
$this->statement->data_seek($row);
return $this->next();
}
public function numRecords() {
return $this->statement->num_rows();
}
public function nextRecord() {
// Skip data if out of data
if (!$this->statement->fetch()) {
return false;
}
// Dereferenced row
$row = array();
foreach($this->boundValues as $key => $value) {
$row[$key] = $value;
}
return $row;
}
public function rewind() {
return $this->seek(0);
}
}