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.

228 lines
5.5 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 Exception('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. * @return int Affected rows count
  82. */
  83. public function insert($table, $bind)
  84. {
  85. $columns = array();
  86. foreach ($bind as $col => $val) {
  87. $columns[] = $this->quoteIdentifier($col);
  88. }
  89. $values = array_values($bind);
  90. $sql = 'INSERT INTO ' . $this->quoteIdentifier($table)
  91. . ' (' . implode(', ', $columns) . ') VALUES (' . $this->quote($values) . ')';
  92. return $this->query($sql)->affectedRows();
  93. }
  94. /**
  95. * @param string $table
  96. * @param array $bind
  97. * @param mixed $where
  98. * @return int
  99. */
  100. public function update($table, $bind, $where = '')
  101. {
  102. $set = array();
  103. foreach ($bind as $col => $val) {
  104. $set[] = $this->quoteIdentifier($col) . '=' . $this->quote($val);
  105. }
  106. $where = $this->whereExpr($where);
  107. $sql = 'UPDATE ' . $this->quoteIdentifier($table) . ' SET ' . implode(', ', $set)
  108. . (($where) ? (' WHERE ' . $where) : '');
  109. return $this->query($sql)->affectedRows();
  110. }
  111. /**
  112. * @param string $table
  113. * @param mixed $where
  114. * @return int
  115. */
  116. public function delete($table, $where = '')
  117. {
  118. $where = $this->whereExpr($where);
  119. $sql = 'DELETE FROM ' . $this->quoteIdentifier($table) . (($where) ? (' WHERE ' . $where) : '');
  120. return $this->query($sql)->affectedRows();
  121. }
  122. /**
  123. * @param mixed $value
  124. * @return string
  125. */
  126. public function quote($value)
  127. {
  128. if ($value instanceof DbExpr) {
  129. return (string) $value;
  130. }
  131. if (is_array($value)) {
  132. foreach ($value as &$val) {
  133. $val = $this->quote($val);
  134. }
  135. return implode(', ', $value);
  136. }
  137. return $this->driverQuote($value);
  138. }
  139. /**
  140. * @param string $ident
  141. * @return string
  142. */
  143. public function quoteIdentifier($ident)
  144. {
  145. $ident = explode('.', $ident);
  146. if (!is_array($ident)) {
  147. $ident = array($ident);
  148. }
  149. foreach ($ident as &$segment) {
  150. $segment = $this->identifier_quote . $segment . $this->identifier_quote;
  151. }
  152. return implode('.', $ident);
  153. }
  154. public function quoteInto($text, $value)
  155. {
  156. $pos = strpos($text, '?');
  157. if ($pos === false) {
  158. return $text;
  159. }
  160. return mb_substr($text, 0, $pos) . $this->quote($value) . mb_substr($text, $pos + 1);
  161. }
  162. /**
  163. * @param mixed $where
  164. * @return string
  165. */
  166. protected function whereExpr($where)
  167. {
  168. if (empty($where)) {
  169. return $where;
  170. }
  171. if (!is_array($where)) {
  172. $where = array($where);
  173. }
  174. foreach ($where as $cond => &$term) {
  175. if (is_int($cond)) {
  176. if ($term instanceof DbExpr) {
  177. $term = (string) $term;
  178. }
  179. } else {
  180. $term = $this->quoteInto($cond, $term);
  181. }
  182. }
  183. return implode(' AND ', $where);
  184. }
  185. /* Abstract methods */
  186. /**
  187. * @return DbStatement
  188. */
  189. abstract public function prepare($sql);
  190. abstract public function getInsertId($table = null, $key = null);
  191. abstract public function isConnected();
  192. abstract public function disconnect();
  193. abstract protected function connect();
  194. abstract protected function driverQuote($value);
  195. abstract protected function driverBeginTransaction();
  196. abstract protected function driverCommitTransaction();
  197. abstract protected function driverRollbackTransaction();
  198. }