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.

235 lines
6.3 KiB

10 years ago
10 years ago
10 years ago
10 years ago
  1. <?php namespace Majestic\Model;
  2. /**
  3. * @copyright NetMonsters <team@netmonsters.ru>
  4. * @link http://netmonsters.ru
  5. * @package Majestic
  6. * @subpackage db
  7. * @since 2011-11-11
  8. */
  9. abstract class SqlDbDriver extends DbDriver
  10. {
  11. protected $identifier_quote = '`';
  12. public function beginTransaction()
  13. {
  14. $this->connect();
  15. $this->driverBeginTransaction();
  16. return $this;
  17. }
  18. public function commit()
  19. {
  20. $this->connect();
  21. $this->driverCommitTransaction();
  22. return $this;
  23. }
  24. public function rollback()
  25. {
  26. $this->connect();
  27. $this->driverRollbackTransaction();
  28. return $this;
  29. }
  30. /**
  31. * @param string $table
  32. * @param mixed $data
  33. * @param mixed $on_duplicate
  34. * @return int Affected rows count
  35. */
  36. public function insert($table, $data, $on_duplicate = array())
  37. {
  38. $columns = array();
  39. foreach ($data as $col => $val) {
  40. $columns[] = $this->quoteIdentifier($col);
  41. }
  42. $values = array_values($data);
  43. $sql = 'INSERT INTO ' . $this->quoteIdentifier($table)
  44. . ' (' . implode(', ', $columns) . ') VALUES (' . $this->quote($values) . ')';
  45. return $this->query($sql)->affectedRows();
  46. }
  47. /**
  48. * @param string $table
  49. * @param array $data
  50. * @param mixed $condition
  51. * @return int Number of updated rows
  52. */
  53. public function update($table, $data, $condition = '')
  54. {
  55. $set = array();
  56. foreach ($data as $col => $val) {
  57. $set[] = $this->quoteIdentifier($col) . '=' . $this->quote($val);
  58. }
  59. $where = $this->whereExpr($condition);
  60. $sql = 'UPDATE ' . $this->quoteIdentifier($table) . ' SET ' . implode(', ', $set)
  61. . (($where) ? (' WHERE ' . $where) : '');
  62. return $this->query($sql)->affectedRows();
  63. }
  64. /**
  65. * @param string $table
  66. * @param mixed $condition
  67. * @return int
  68. */
  69. public function delete($table, $condition = '')
  70. {
  71. $where = $this->whereExpr($condition);
  72. $sql = 'DELETE FROM ' . $this->quoteIdentifier($table) . (($where) ? (' WHERE ' . $where) : '');
  73. return $this->query($sql)->affectedRows();
  74. }
  75. /**
  76. * @param mixed $value
  77. * @return string
  78. */
  79. public function quote($value)
  80. {
  81. if ($value instanceof DbExpr) {
  82. return (string) $value;
  83. }
  84. if (is_array($value)) {
  85. foreach ($value as &$val) {
  86. $val = $this->quote($val);
  87. }
  88. return implode(', ', $value);
  89. }
  90. return $this->driverQuote($value);
  91. }
  92. /**
  93. * @param string $ident
  94. * @return string
  95. */
  96. public function quoteIdentifier($ident)
  97. {
  98. $ident = explode('.', $ident);
  99. foreach ($ident as &$segment) {
  100. if (!preg_match('/^(\?|:[A-z][A-z0-9_]*+|\*)$/u', $segment)) {
  101. $segment = $this->identifier_quote . $segment . $this->identifier_quote;
  102. }
  103. }
  104. return implode('.', $ident);
  105. }
  106. public function quoteInto($text, $value)
  107. {
  108. $pos = mb_strpos($text, '?');
  109. if ($pos === false) {
  110. return $text;
  111. }
  112. return mb_substr($text, 0, $pos) . $this->quote($value) . mb_substr($text, $pos + 1);
  113. }
  114. /**
  115. * @param mixed $where
  116. * @return string
  117. * @throws \ErrorException
  118. */
  119. public function whereExpr($where)
  120. {
  121. if (empty($where)) {
  122. return $where;
  123. }
  124. if (!is_array($where)) {
  125. $where = array($where);
  126. }
  127. foreach ($where as $cond => &$term) {
  128. if (is_int($cond)) {
  129. if (is_int($term)) {
  130. throw new \ErrorException('Condition in where expression as integer. ' . $term);
  131. }
  132. if ($term instanceof DbExpr) {
  133. $term = (string) $term;
  134. }
  135. } else {
  136. if (is_array($term)) {
  137. foreach ($term as &$val) {
  138. $val = $this->driverQuote($val);
  139. }
  140. $term = new DbExpr('(' . implode(',', $term) . ')');
  141. }
  142. $term = $this->quoteInto($cond, $term);
  143. }
  144. }
  145. return implode(' AND ', $where);
  146. }
  147. /**
  148. * @param mixed $group_by
  149. * @return string
  150. * @throws \ErrorException
  151. */
  152. public function groupByExpr($group_by)
  153. {
  154. if (empty($group_by)) {
  155. return $group_by;
  156. }
  157. if (!is_array($group_by)) {
  158. $group_by = array($group_by);
  159. }
  160. foreach ($group_by as &$term) {
  161. if ($term instanceof DbExpr) {
  162. $term = (string) $term;
  163. } else {
  164. $term = $this->quoteIdentifier($term);
  165. }
  166. }
  167. return implode(',', $group_by);
  168. }
  169. /**
  170. * @param $select array
  171. * @param $distinct string|bool
  172. * @return string
  173. */
  174. public function selectExpr($select, $distinct = false)
  175. {
  176. if (empty($distinct) && empty($select)) {
  177. return '*';
  178. }
  179. if (!is_array($select)) {
  180. $select = array($select);
  181. }
  182. if ($distinct) {
  183. $distinct = ((is_bool($distinct)) ? '*' : $this->quoteIdentifier($distinct));
  184. array_unshift($select, new DbExpr('DISTINCT ' . $distinct));
  185. }
  186. foreach ($select as $field => &$term) {
  187. if (is_int($field)) {
  188. if ($term instanceof DbExpr) {
  189. $term = (string) $term;
  190. } else {
  191. $term = $this->quoteIdentifier($term);
  192. }
  193. } else {
  194. $term = $this->quoteIdentifier($field) . ' as ' . $this->quoteIdentifier($term);
  195. }
  196. }
  197. return implode(',', $select);
  198. }
  199. public function limitExpr($limit)
  200. {
  201. if (empty($limit)) {
  202. return $limit;
  203. }
  204. return implode(',',array_map(function($item){return intval($item);},explode(',',$limit)));
  205. }
  206. abstract protected function driverQuote($value);
  207. abstract protected function driverBeginTransaction();
  208. abstract protected function driverCommitTransaction();
  209. abstract protected function driverRollbackTransaction();
  210. }