* @package Mammut\DB\Adapter\MySQL */ class Statement extends \Mammut\DB\Statement { /** * @var \mysqli_stmt */ protected $stmt; /** * @var DB */ protected $dbinstance; /** * @var \mysqli_result */ protected $meta; /** * @var array */ protected $fields; /** * Create a new statement instance * * @param \mysqli $db * The database link * @param \mysqli_stmt $stmt * The statement instance * @param string $sql * SQL query of the statement * @param DB $dbinstance * The database link object */ public function __construct(\mysqli $db, \mysqli_stmt $stmt, $sql, DB $dbinstance) { $this->db = &$db; $this->stmt = &$stmt; $this->dbinstance = $dbinstance; $this->query = $sql; } public function execute(array $param = array()) { $data = self::prepareData($param); // workaround to the 'type, var, var,...' call, if(count($param) > 0) call_user_func_array(array($this->stmt,'bind_param'), $data); $this->dbinstance->isQueryStoring() && $starttime = microtime(true); $stmt_res = $this->stmt->execute(); $this->stmt->store_result(); $this->meta = $this->stmt->result_metadata(); $this->dbinstance->isQueryStoring() && $this->dbinstance->storeQuery($this->query, $param, microtime(true) - $starttime); if(!empty($this->meta)) { $this->fields = $this->meta->fetch_fields(); } if($this->stmt->errno != 0) throw new \Mammut\DB\DBException($this->stmt->error, $this->stmt->errno); $this->executed = true; } public static function prepareData(array &$param) { $typestr = ''; $refs = array(); foreach($param as $k=>&$p) { if ($p instanceof \DateTime) $p = $p->format('Y-m-d H:i:s'); if(is_int($p) || is_long($p)) $typestr .= 'i'; elseif(is_double($p) || is_float($p)) $typestr .= 'd'; else $typestr .= 's'; $refs[$k] = &$param[$k]; // php >= 5.3 needs references, not values } $data = array_merge(array($typestr), $refs); return $data; } public function getColumns() { if (!$this->executed) throw new IllegalStateException('not executed'); return $this->result->getColumns(); } public function getColumnInfo($column) { throw new ImplementationException('not implemented'); } public function getColumnCount() { if (!$this->executed) throw new IllegalStateException('not executed'); if(empty($this->stmt)) return -1; return $this->stmt->field_count; } public function getRowNumber() { if (!$this->executed) throw new IllegalStateException('not executed'); if(empty($this->stmt)) return -1; return $this->rownr; } public function getRowCount() { if (!$this->executed) throw new IllegalStateException('not executed'); if(empty($this->stmt)) return -1; if (($this->stmt->num_rows == 0) && ($this->stmt->affected_rows > 0)) return $this->stmt->affected_rows; return $this->stmt->num_rows; } public function fetchRow() { $result = array(); $a = array(); for($i = 0; $i < $this->stmt->field_count; $i++) { $a[$i] = NULL; $result[$i] = &$a[$i]; } call_user_func_array(array($this->stmt,'bind_result'), $result); if(!$this->stmt->fetch()) return false; $this->rownr++; $i = 0; foreach($result as $k=>$v) { $result[$k] = \Mammut\DB\Result::convertDBResultValue($v, $this->fields[$i]->type); $i++; } return $result; } public function fetchArray() { if (!$this->executed) throw new IllegalStateException('not executed'); $result = array(); $a = array(); $result = array(); foreach($this->fields as $field) { $a[$field->name] = NULL; $result[$field->name] = &$a[$field->name]; } call_user_func_array(array($this->stmt,'bind_result'), $result); if(!$this->stmt->fetch()) return false; $this->rownr++; $i = 0; foreach($result as $k=>$v) { $result[$k] = Result::convertDBResultValue($v, $this->fields[$i]->type); $i++; } return $result; } public function fetchObject($class = false, $param = array()) { if (!$this->executed) throw new IllegalStateException('not executed'); if($class) { $ref = new \ReflectionClass($class); $obj = $ref->newInstanceArgs($param); unset($ref); } else $obj = new \stdClass(); $a = array(); $result = array(); foreach($this->fields as $field) { $a[$field->name] = NULL; $result[$field->name] = &$a[$field->name]; } call_user_func_array(array($this->stmt,'bind_result'), $result); if(!$this->stmt->fetch()) return false; $this->rownr++; $i = 0; foreach($result as $k=>$v) { $obj->{$k} = Result::convertDBResultValue($v, $this->fields[$i]->type); $i++; } return $obj; } public function free() { if(isset($this->stmt)) $this->stmt->free_result(); $this->executed = false; } public function close() { $this->stmt->free_result(); } public function __destruct() { $this->close(); } }