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
4.9 KiB
180 lines
4.9 KiB
<?php
|
|
/**
|
|
* @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 GeneralException('Placeholder must be an integer or string');
|
|
}
|
|
if (is_object($value) && ! ($value instanceof DbExpr)) {
|
|
throw new 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 GeneralException
|
|
*/
|
|
public function fetch($style = \Majestic\Db::FETCH_OBJ)
|
|
{
|
|
if (!$this->result) {
|
|
return false;
|
|
}
|
|
|
|
switch ($style) {
|
|
case \Majestic\Db::FETCH_OBJ:
|
|
$row = $this->result->fetch_object();
|
|
break;
|
|
case \Majestic\Db::FETCH_NUM:
|
|
$row = $this->result->fetch_array(MYSQLI_NUM);
|
|
break;
|
|
case \Majestic\Db::FETCH_ASSOC:
|
|
$row = $this->result->fetch_assoc();
|
|
break;
|
|
case \Majestic\Db::FETCH_BOTH:
|
|
$row = $this->result->fetch_array(MYSQLI_BOTH);
|
|
break;
|
|
default:
|
|
throw new 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(\Majestic\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 (Config::get('PROFILER_DETAILS')) {
|
|
$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 GeneralException($message, $mysqli->errno);
|
|
}
|
|
if ($result instanceof MySQLi_Result) {
|
|
$this->result = $result;
|
|
}
|
|
return true;
|
|
}
|
|
}
|