2015-04-29 07:32:57 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
2015-08-24 06:15:38 +02:00
|
|
|
*
|
|
|
|
* @package framework
|
|
|
|
* @subpackage model
|
2015-04-29 07:32:57 +02:00
|
|
|
*/
|
|
|
|
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();
|
2015-07-05 05:06:37 +02:00
|
|
|
|
|
|
|
call_user_func_array(array($this->statement, 'bind_result'), $variables);
|
2015-04-29 07:32:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|