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.

229 lines
5.6 KiB

  1. <?php
  2. /**
  3. * @copyright NetMonsters <team@netmonsters.ru>
  4. * @link http://netmonsters.ru
  5. * @package Majestic
  6. * @subpackage db
  7. * @since 2010-02-16
  8. * @version SVN: $Id$
  9. * @filesource $URL$
  10. */
  11. abstract class DbDriver
  12. {
  13. protected $identifier_quote = '`';
  14. /**
  15. * Database connection
  16. *
  17. * @var object
  18. */
  19. protected $connection = null;
  20. /**
  21. * Configuration data
  22. *
  23. * @var array
  24. */
  25. protected $config = array();
  26. public function __construct($config)
  27. {
  28. $this->checkConfig($config);
  29. $this->config = $config;
  30. }
  31. protected function checkConfig($config)
  32. {
  33. $required = array('database', 'username', 'password', 'hostname');
  34. foreach ($required as $option) {
  35. if (!isset($config[$option])) {
  36. throw new GeneralException('Configuration must have a "' . $option . '".');
  37. }
  38. }
  39. }
  40. public function getConnection()
  41. {
  42. $this->connect();
  43. return $this->connection;
  44. }
  45. public function beginTransaction()
  46. {
  47. $this->connect();
  48. $this->driverBeginTransaction();
  49. return $this;
  50. }
  51. public function commit()
  52. {
  53. $this->connect();
  54. $this->driverCommitTransaction();
  55. return $this;
  56. }
  57. public function rollback()
  58. {
  59. $this->connect();
  60. $this->driverRollbackTransaction();
  61. return $this;
  62. }
  63. /**
  64. * @param string $sql
  65. * @param mixed $params
  66. * @return DbStatement
  67. */
  68. public function query($sql, $params = array())
  69. {
  70. $this->connect();
  71. if (!is_array($params)) {
  72. $params = array($params);
  73. }
  74. $stmt = $this->prepare($sql);
  75. $stmt->execute($params);
  76. return $stmt;
  77. }
  78. /**
  79. * @param string $table
  80. * @param mixed $bind
  81. * @param mixed $on_duplicate
  82. * @return int Affected rows count
  83. */
  84. public function insert($table, $bind, $on_duplicate = array())
  85. {
  86. $columns = array();
  87. foreach ($bind as $col => $val) {
  88. $columns[] = $this->quoteIdentifier($col);
  89. }
  90. $values = array_values($bind);
  91. $sql = 'INSERT INTO ' . $this->quoteIdentifier($table)
  92. . ' (' . implode(', ', $columns) . ') VALUES (' . $this->quote($values) . ')';
  93. return $this->query($sql)->affectedRows();
  94. }
  95. /**
  96. * @param string $table
  97. * @param array $bind
  98. * @param mixed $where
  99. * @return int
  100. */
  101. public function update($table, $bind, $where = '')
  102. {
  103. $set = array();
  104. foreach ($bind as $col => $val) {
  105. $set[] = $this->quoteIdentifier($col) . '=' . $this->quote($val);
  106. }
  107. $where = $this->whereExpr($where);
  108. $sql = 'UPDATE ' . $this->quoteIdentifier($table) . ' SET ' . implode(', ', $set)
  109. . (($where) ? (' WHERE ' . $where) : '');
  110. return $this->query($sql)->affectedRows();
  111. }
  112. /**
  113. * @param string $table
  114. * @param mixed $where
  115. * @return int
  116. */
  117. public function delete($table, $where = '')
  118. {
  119. $where = $this->whereExpr($where);
  120. $sql = 'DELETE FROM ' . $this->quoteIdentifier($table) . (($where) ? (' WHERE ' . $where) : '');
  121. return $this->query($sql)->affectedRows();
  122. }
  123. /**
  124. * @param mixed $value
  125. * @return string
  126. */
  127. public function quote($value)
  128. {
  129. if ($value instanceof DbExpr) {
  130. return (string) $value;
  131. }
  132. if (is_array($value)) {
  133. foreach ($value as &$val) {
  134. $val = $this->quote($val);
  135. }
  136. return implode(', ', $value);
  137. }
  138. return $this->driverQuote($value);
  139. }
  140. /**
  141. * @param string $ident
  142. * @return string
  143. */
  144. public function quoteIdentifier($ident)
  145. {
  146. $ident = explode('.', $ident);
  147. if (!is_array($ident)) {
  148. $ident = array($ident);
  149. }
  150. foreach ($ident as &$segment) {
  151. $segment = $this->identifier_quote . $segment . $this->identifier_quote;
  152. }
  153. return implode('.', $ident);
  154. }
  155. public function quoteInto($text, $value)
  156. {
  157. $pos = mb_strpos($text, '?');
  158. if ($pos === false) {
  159. return $text;
  160. }
  161. return mb_substr($text, 0, $pos) . $this->quote($value) . mb_substr($text, $pos + 1);
  162. }
  163. /**
  164. * @param mixed $where
  165. * @return string
  166. */
  167. protected function whereExpr($where)
  168. {
  169. if (empty($where)) {
  170. return $where;
  171. }
  172. if (!is_array($where)) {
  173. $where = array($where);
  174. }
  175. foreach ($where as $cond => &$term) {
  176. if (is_int($cond)) {
  177. if ($term instanceof DbExpr) {
  178. $term = (string) $term;
  179. }
  180. } else {
  181. $term = $this->quoteInto($cond, $term);
  182. }
  183. }
  184. return implode(' AND ', $where);
  185. }
  186. /* Abstract methods */
  187. /**
  188. * @return DbStatement
  189. */
  190. abstract public function prepare($sql);
  191. abstract public function getInsertId($table = null, $key = null);
  192. abstract public function isConnected();
  193. abstract public function disconnect();
  194. abstract protected function connect();
  195. abstract protected function driverQuote($value);
  196. abstract protected function driverBeginTransaction();
  197. abstract protected function driverCommitTransaction();
  198. abstract protected function driverRollbackTransaction();
  199. }