You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
5.0 KiB

<?php namespace Majestic\Model;
/**
* @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru
* @package Majestic
* @subpackage db
* @since 2010-02-19
*/
/**
* @property MySQLiDriver $driver
* @property \MySQLi_Result $result
*/
class MySQLiStatement extends DbStatement
{
protected $map = null;
public function bindParam($param, &$value)
{
if ($this->map === null) {
$this->mapPlaceholders();
}
if (count($this->map) > 0) {
if (!is_string($param) && !is_int($param)) {
throw new \Majestic\Exception\GeneralException('Placeholder must be an integer or string');
}
if (is_object($value) && ! ($value instanceof DbExpr)) {
throw new \Majestic\Exception\GeneralException('Objects excepts DbExpr not allowed.');
}
if (isset($this->map[$param])) {
$this->params[$param] = &$value;
return true;
}
}
return false;
}
protected function mapPlaceholders()
{
$matches = array();
if(preg_match_all('/(\?|:[A-z][A-z0-9_]*+)/u', $this->request, $matches, PREG_OFFSET_CAPTURE)) {
$noname = 0;
foreach ($matches[0] as $id=>$match) {
$match[2] = $matches[1][$id][0];
$name = ($match[2][0] === ':') ? ltrim($match[2], ':') : $noname++;
$this->map[$name]['placeholder'] = $match[0];
$this->map[$name]['offset'][] = $match[1];
}
}
}
protected function assemble()
{
if (empty($this->map)) {
return $this->request;
}
$query = $this->request;
$placeholders = array();
foreach($this->map as $name => $place) {
$value = $this->driver->quote($this->params[$name]);
foreach ($place['offset'] as $offset) {
$placeholders[$offset] = array('placeholder' => $place['placeholder'], 'value' => $value);
}
}
ksort($placeholders);
$increment = 0;
foreach($placeholders as $current_offset => $placeholder) {
$offset = $current_offset + $increment;
$length = mb_strlen($placeholder['placeholder']);
$query = mb_substr($query, 0, $offset) . $placeholder['value'] . mb_substr($query, $offset + $length);
$increment = (($increment - $length) + mb_strlen($placeholder['value']));
}
return $query;
}
/**
* Fetches single row
*
* @param mixed $style
* @return mixed
* @throws \Majestic\Exception\GeneralException
*/
public function fetch($style = Db::FETCH_OBJ)
{
if (!$this->result) {
return false;
}
switch ($style) {
case Db::FETCH_OBJ:
$row = $this->result->fetch_object();
break;
case Db::FETCH_NUM:
$row = $this->result->fetch_array(MYSQLI_NUM);
break;
case Db::FETCH_ASSOC:
$row = $this->result->fetch_assoc();
break;
case Db::FETCH_BOTH:
$row = $this->result->fetch_array(MYSQLI_BOTH);
break;
default:
throw new \Majestic\Exception\GeneralException('Invalid fetch mode "' . $style . '" specified');
}
return $row;
}
/**
* @param string $class
* @return object
*/
public function fetchObject($class = 'stdClass')
{
return $this->result->fetch_object($class);
}
/**
* @return array
*/
public function fetchPairs()
{
$data = array();
while ($row = $this->fetch(Db::FETCH_NUM)) {
$data[$row[0]] = $row[1];
}
return $data;
}
public function close()
{
if ($this->result !== null) {
$this->result->close();
$this->result = null;
}
}
public function affectedRows()
{
return $this->driver->getConnection()->affected_rows;
}
public function numRows()
{
if ($this->result) {
return $this->result->num_rows;
}
return false;
}
public function getMysqliResult()
{
return $this->result;
}
protected function driverExecute($request)
{
/**
* @var \MySQLi
*/
$mysqli = $this->driver->getConnection();
if (\Majestic\Config::get('PROFILER_DETAILS')) {
$profiler = \Majestic\Util\Profiler\Profiler::getInstance()->profilerCommand('MySQL', $request);
$result = $mysqli->query($request);
$profiler->end();
} else {
$result = $mysqli->query($request);
}
if ($result === false) {
$message = $mysqli->error . "\nQuery: \"" . $request . '"';
throw new \Majestic\Exception\GeneralException($message, $mysqli->errno);
}
if ($result instanceof \MySQLi_Result) {
$this->result = $result;
}
return true;
}
}