* @link http://netmonsters.ru * @package Majestic * @subpackage db * @since 2010-02-19 * @version SVN: $Id$ * @filesource $URL$ */ abstract class DbStatement { /** * @var DbDriver */ protected $driver; /** * @var string */ protected $sql; protected $map = null; protected $params = array(); protected $result; public function __construct($driver, $sql) { $this->driver = $driver; $this->sql = $sql; } 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 array 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; } /** * @param array $params * @return bool */ public function execute($params = null) { if (is_array($params)) { foreach ($params as $param => &$value) { $this->bindParam($param, $value); } } return $this->driverExecute($this->assemble()); } protected function mapPlaceholders() { $matches = array(); if(preg_match_all('/(\?|:[A-z0-9_]+)/u', $this->sql, $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->sql; } $query = $this->sql; $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; } public function __destruct() { $this->close(); } /** * @param mixed $style * @return array */ public function fetchAll($style = Db::FETCH_OBJ) { $data = array(); while ($row = $this->fetch($style)) { $data[] = $row; } return $data; } /** * @param string $field */ public function fetchColumn($field) { $data = array(); while ($row = $this->fetch(Db::FETCH_ASSOC)) { $data[] = $row[$field]; } return $data; } /** * @param string $field */ public function fetchField($field) { $row = $this->fetch(Db::FETCH_ASSOC); if (isset($row[$field])) { return $row[$field]; } return false; } /** * @return array */ public function fetchPairs() { $data = array(); while ($row = $this->fetch(Db::FETCH_NUM)) { $data[$row[0]] = $row[1]; } return $data; } /* Abstract methods */ abstract public function fetch($style = Db::FETCH_OBJ); abstract public function fetchObject($class = 'stdClass'); abstract public function close(); /** * @return int */ abstract public function affectedRows(); abstract public function numRows(); /** * @return bool */ abstract protected function driverExecute($sql); }