* @link http://netmonsters.ru * @package Majestic * @subpackage db * @since 2011-11-11 */ abstract class SqlDbDriver extends DbDriver { protected $identifier_quote = '`'; public function beginTransaction() { $this->connect(); $this->driverBeginTransaction(); return $this; } public function commit() { $this->connect(); $this->driverCommitTransaction(); return $this; } public function rollback() { $this->connect(); $this->driverRollbackTransaction(); return $this; } /** * @param string $table * @param mixed $data * @param mixed $on_duplicate * @return int Affected rows count */ public function insert($table, $data, $on_duplicate = array()) { $columns = array(); foreach ($data as $col => $val) { $columns[] = $this->quoteIdentifier($col); } $values = array_values($data); $sql = 'INSERT INTO ' . $this->quoteIdentifier($table) . ' (' . implode(', ', $columns) . ') VALUES (' . $this->quote($values) . ')'; return $this->query($sql)->affectedRows(); } /** * @param string $table * @param array $data * @param mixed $condition * @return int Number of updated rows */ public function update($table, $data, $condition = '') { $set = array(); foreach ($data as $col => $val) { $set[] = $this->quoteIdentifier($col) . '=' . $this->quote($val); } $where = $this->whereExpr($condition); $sql = 'UPDATE ' . $this->quoteIdentifier($table) . ' SET ' . implode(', ', $set) . (($where) ? (' WHERE ' . $where) : ''); return $this->query($sql)->affectedRows(); } /** * @param string $table * @param mixed $condition * @return int */ public function delete($table, $condition = '') { $where = $this->whereExpr($condition); $sql = 'DELETE FROM ' . $this->quoteIdentifier($table) . (($where) ? (' WHERE ' . $where) : ''); return $this->query($sql)->affectedRows(); } /** * @param mixed $value * @return string */ public function quote($value) { if ($value instanceof DbExpr) { return (string) $value; } if (is_array($value)) { foreach ($value as &$val) { $val = $this->quote($val); } return implode(', ', $value); } return $this->driverQuote($value); } /** * @param string $ident * @return string */ public function quoteIdentifier($ident) { $ident = explode('.', $ident); foreach ($ident as &$segment) { if (!preg_match('/^(\?|:[A-z][A-z0-9_]*+|\*)$/u', $segment)) { $segment = $this->identifier_quote . $segment . $this->identifier_quote; } } return implode('.', $ident); } public function quoteInto($text, $value) { $pos = mb_strpos($text, '?'); if ($pos === false) { return $text; } return mb_substr($text, 0, $pos) . $this->quote($value) . mb_substr($text, $pos + 1); } /** * @param mixed $where * @return string * @throws \ErrorException */ public function whereExpr($where) { if (empty($where)) { return $where; } if (!is_array($where)) { $where = array($where); } foreach ($where as $cond => &$term) { if (is_int($cond)) { if (is_int($term)) { throw new \ErrorException('Condition in where expression as integer. ' . $term); } if ($term instanceof DbExpr) { $term = (string) $term; } } else { if (is_array($term)) { foreach ($term as &$val) { $val = $this->driverQuote($val); } $term = new DbExpr('(' . implode(',', $term) . ')'); } $term = $this->quoteInto($cond, $term); } } return implode(' AND ', $where); } /** * @param mixed $group_by * @return string * @throws \ErrorException */ public function groupByExpr($group_by) { if (empty($group_by)) { return $group_by; } if (!is_array($group_by)) { $group_by = array($group_by); } foreach ($group_by as &$term) { if ($term instanceof DbExpr) { $term = (string) $term; } else { $term = $this->quoteIdentifier($term); } } return implode(',', $group_by); } /** * @param $select array * @param $distinct string|bool * @return string */ public function selectExpr($select, $distinct = false) { if (empty($distinct) && empty($select)) { return '*'; } if (!is_array($select)) { $select = array($select); } if ($distinct) { $distinct = ((is_bool($distinct)) ? '*' : $this->quoteIdentifier($distinct)); array_unshift($select, new DbExpr('DISTINCT ' . $distinct)); } foreach ($select as $field => &$term) { if (is_int($field)) { if ($term instanceof DbExpr) { $term = (string) $term; } else { $term = $this->quoteIdentifier($term); } } else { $term = $this->quoteIdentifier($field) . ' as ' . $this->quoteIdentifier($term); } } return implode(',', $select); } public function limitExpr($limit) { if (empty($limit)) { return $limit; } return implode(',',array_map(function($item){return intval($item);},explode(',',$limit))); } abstract protected function driverQuote($value); abstract protected function driverBeginTransaction(); abstract protected function driverCommitTransaction(); abstract protected function driverRollbackTransaction(); }