git-svn-id: svn+ssh://code.netmonsters.ru/svn/majestic/branches/evo@149 4cb57b5f-5bbd-dd11-951b-001d605cbbc5
		
			
				
	
	
		
			186 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			186 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * @copyright NetMonsters <team@netmonsters.ru>
 | |
|  * @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 Exception('Placeholder must be an array or string');
 | |
|             }
 | |
|             if (is_object($value) && ! ($value instanceof DbExpr)) {
 | |
|                 throw new Exception('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);
 | |
| }
 |