PageRenderTime 51ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/berry/lib/berry/sql/control.php

http://goodgirl.googlecode.com/
PHP | 351 lines | 229 code | 95 blank | 27 comment | 40 complexity | b2fac9f9e37df9aca8ab6cc9070c053f MD5 | raw file
  1. <?php /* `,
  2. ,\, #
  3. B E R R Y |/ ?
  4. <http://goodgirl.ru/berry> | ~ )\
  5. <http://goodgirl.ru/berry/license> /__/\ \____
  6. / \_/ \
  7. ???? zloy ? ???????? <http://lexa.cutenews.ru> / <_ ____,_-/\ __
  8. ---------------------------------------------------------/___/_____ \--'\|/----
  9. \/|*/
  10. abstract class SQL_Control extends SQL_Vars implements Countable {
  11. ////////////////////////////////////////////////////////////////////////////////
  12. function create(){
  13. $query = self::query($this->build('create'))->exec();
  14. if ($query === null)
  15. return 0;
  16. $result = self::alter();
  17. return ($result === 0 ? 1 : $result);
  18. }
  19. ////////////////////////////////////////////////////////////////////////////////
  20. function alter(){
  21. if (!$query = $this->build('alter'))
  22. return 0;
  23. cache::remove('sql/schema/'.$this->table.'.php');
  24. return self::query($query)->exec();
  25. }
  26. ////////////////////////////////////////////////////////////////////////////////
  27. function save($full = false){
  28. $result = array();
  29. self::_check();
  30. self::_save($result);
  31. if (!array_key_exists($this->alias, $result))
  32. $result = array($this->alias => array(0)) + $result;
  33. if ($full)
  34. return $result;
  35. self::_fetch_col($result = $result[$this->alias]);
  36. return reset($result);
  37. }
  38. ////////////////////////////////////////////////////////////////////////////////
  39. protected function _check(){
  40. if ($this->into){
  41. foreach ($this->values as $k => $v)
  42. if (!check::is_valid($this->check, array_combine($this->into, $v)))
  43. throw new Check_Except($this->check, $this->alias);
  44. } elseif (!check::is_valid($this->check, $this->values)){
  45. throw new Check_Except($this->check, $this->alias);
  46. }
  47. foreach ($this->parallel as $class)
  48. if ($class instanceof SQL)
  49. $class->_check();
  50. }
  51. ////////////////////////////////////////////////////////////////////////////////
  52. protected function _save(&$result, $is_parallel = false){
  53. $values = $this->values;
  54. $belongs = array();
  55. foreach ($values as $k => $v)
  56. if (self::_is_HABTM($k)){
  57. $v = array_unique($v);
  58. sort($v);
  59. unset($values[$k]);
  60. if (self::$cache[$this->alias][$k] != $v)
  61. $belongs[substr($k, 0, -4)] = $v;
  62. } elseif ($k[0] == '#' and $result[$v]){
  63. $first = array_shift($result[$v]);
  64. $values[substr($k, 1)] = $first;
  65. $result[$v][] = $first;
  66. unset($values[$k]);
  67. if (
  68. !$this->where and !$this->relations['#'] and
  69. $result[$this->alias] and $result[$this->alias][0]
  70. )
  71. $this->where($this->primary_key.' = ?d', $result[$this->alias][0]);
  72. }
  73. if ($values){ if (!$this->where){ if (!$into = $this->into){ $into = array_keys($values);
  74. $values = array(array_values($values));
  75. }
  76. $args = array_merge(array($into), $values, $this->placeholders);
  77. $count = self::query($this->build('insert'), $args)->exec();
  78. if ($count !== null){
  79. $id = self::$connection['link']->lastInsertId();
  80. $result[$this->alias][] = (int)$id;
  81. if ($id and b::len($values) > 1)
  82. $result[$this->alias] = array_merge(
  83. $result[$this->alias],
  84. range(($id + 1), ($id + $count - 1))
  85. );
  86. } else { $result[$this->alias][] = $count; }
  87. } else {
  88. $args = array_merge(array($values), $this->placeholders);
  89. $result[$this->alias][] = self::query($this->build('update'), $args)->exec();
  90. }
  91. if (end($result[$this->alias]) === null)
  92. return;
  93. }
  94. foreach ($belongs as $k => $v){
  95. $local = $this->relations[$k]['local'];
  96. $foreign = $this->relations[$k]['foreign'];
  97. $class = self::table($foreign['alias1']);
  98. $id = ($this->id ? $this->id : $result[$local['alias']][0]);
  99. $class->where($foreign['field1'].' = ?', $id)->delete();
  100. $class->where = array();
  101. foreach ($v as $i)
  102. $class->values(array(
  103. $foreign['field1'] => $id,
  104. $foreign['field3'] => $i
  105. ));
  106. $this->parallel[] = $class;
  107. }
  108. foreach ($this->parallel as $class)
  109. if ($class instanceof SQL)
  110. $class->_save($result, true);
  111. }
  112. ////////////////////////////////////////////////////////////////////////////////
  113. function delete(){
  114. $from = $this->from;
  115. foreach ($this->from as $k => $v)
  116. if ($pos = stripos($v, ' as '))
  117. $from[$k] = trim(substr($v, 0, $pos));
  118. return self::query($this->build('delete'))->exec();
  119. $args = $this->placeholders;
  120. array_unshift($args, $this->build('delete'), $from, ($this->limit ? self::SKIP : $from));
  121. return call_user_func_array(array(self::$connection, 'query'), $args);
  122. }
  123. ////////////////////////////////////////////////////////////////////////////////
  124. function fetch(){
  125. if (!$this->select)
  126. $this->select[] = '*';
  127. $query = $this->build('select');
  128. $self = clone $this;
  129. if ($this->multiple and !$this->group_by and ($this->limit or $this->where)){
  130. $class = clone $this;
  131. $class->select = $class->group_by = array($this->primary_key);
  132. $class->join = array();
  133. if (!$ids = $class->query($class->build('select'))->fetch_col())
  134. return array();
  135. $self->where = $self->placeholders = array();
  136. $self->having = array();
  137. $self->limit = $self->offset = 0;
  138. $self->where_between($this->primary_key, $ids);
  139. $query = $self->build('select');
  140. }
  141. return $self->query($query)->fetch();
  142. }
  143. ////////////////////////////////////////////////////////////////////////////////
  144. function fetch_array(){
  145. $class = clone $this;
  146. if (!$this->select)
  147. $class->select[] = '*';
  148. $this->build('select');
  149. if ($multiple = array_unique($this->multiple)){ $class->select[] = $this->primary_key.' as __';
  150. foreach ($multiple as $k => $v){
  151. $vars = self::vars(inflector::singular(end(explode('.', $v))));
  152. $field = $v.'.'.($vars['primary_key'] ? $vars['primary_key'] : 'id');
  153. $class->select[] = $field.' as __'.$v;
  154. }
  155. }
  156. if (!$array = $class->fetch())
  157. return array();
  158. if (!$multiple){
  159. $result = arr::assoc($array);
  160. return ($this->id ? $result[0] : $result);
  161. }
  162. $result = $repl = $values = array();
  163. $func = create_function('$a, $b', 'return (substr_count($a, ".") < substr_count($b, "."));');
  164. foreach ($array as $row){ $i = $row['__'];
  165. unset($row['__']);
  166. if (!isset($result[$i]))
  167. $result[$i] = array();
  168. foreach ($row as $k => $v)
  169. if (substr($k, 0, 2) == '__'){
  170. unset($row[$k]);
  171. if ($v !== null){ $key = substr($k, 2);
  172. $repl[$key] = $key.'.'.$v;
  173. }
  174. } elseif ($v === null){ unset($row[$k]); }
  175. uasort($repl, $func);
  176. foreach ($row as $k => $v){ $key = str_replace(array_keys($repl), array_values($repl), $k);
  177. $row[$key] = $v;
  178. if (
  179. ($pos = strrpos($k, '.')) and
  180. isset($repl[$key = substr($k, 0, $pos)])
  181. ) unset($row[$k]);
  182. }
  183. $result[$i] += $row;
  184. }
  185. $result = self::_fetch_array(arr::assoc($result));
  186. $result = array_values($result);
  187. return ($this->id ? $result[0] : $result);
  188. }
  189. ////////////////////////////////////////////////////////////////////////////////
  190. protected static function _fetch_array($array){
  191. $result = array();
  192. foreach ($array as $k => $v){
  193. if (is_array($v))
  194. $v = self::_fetch_array(is_int(key($v)) ? array_values($v) : $v);
  195. $result[$k] = $v;
  196. }
  197. return $result;
  198. }
  199. ////////////////////////////////////////////////////////////////////////////////
  200. function fetch_cell(){
  201. if (is_array($array = self::fetch_col()))
  202. return reset($array);
  203. return $array;
  204. }
  205. ////////////////////////////////////////////////////////////////////////////////
  206. function fetch_col(){
  207. $array = self::fetch();
  208. self::_fetch_col($array);
  209. return ($array ? $array : array());
  210. }
  211. ////////////////////////////////////////////////////////////////////////////////
  212. protected static function _fetch_col(&$v){
  213. if (!is_array($cell = reset($v)))
  214. $v = $cell;
  215. else
  216. array_walk($v, array('self', '_fetch_col'));
  217. }
  218. ////////////////////////////////////////////////////////////////////////////////
  219. function fetch_row(){
  220. if ($array = reset(self::fetch()))
  221. return $array;
  222. return array();
  223. }
  224. ////////////////////////////////////////////////////////////////////////////////
  225. function count(){
  226. $class = clone $this;
  227. $class->select = array('count(*)');
  228. $class->join = $class->order_by = array();
  229. $class->group_by = ($class->group_by ? $class->group_by : array($this->primary_key));
  230. $class->limit = $class->offset = 0;
  231. return array_sum($class->fetch_col());
  232. }
  233. ////////////////////////////////////////////////////////////////////////////////
  234. function exists(){ if (!$this->where)
  235. return;
  236. $class = self::table($this->alias);
  237. $class->select[] = 1;
  238. $class->where = $this->where;
  239. $class->having = $this->having;
  240. $class->limit = 1;
  241. $class->placeholders = $this->placeholders;
  242. return (bool)$class->fetch_cell();
  243. }
  244. ////////////////////////////////////////////////////////////////////////////////
  245. function begin(){
  246. return self::$connection['link']->beginTransaction();
  247. }
  248. ////////////////////////////////////////////////////////////////////////////////
  249. function commit(){ if (!self::$connection['link']->commit())
  250. throw new SQL_Except;
  251. }
  252. ////////////////////////////////////////////////////////////////////////////////
  253. function rollback(){ return self::$connection['link']->rollback();
  254. }
  255. ////////////////////////////////////////////////////////////////////////////////
  256. }