/berry/lib/berry/sql/control.php
PHP | 351 lines | 229 code | 95 blank | 27 comment | 40 complexity | b2fac9f9e37df9aca8ab6cc9070c053f MD5 | raw file
- <?php /* `,
- ,\, #
- B E R R Y |/ ?
- <http://goodgirl.ru/berry> | ~ )\
- <http://goodgirl.ru/berry/license> /__/\ \____
- / \_/ \
- ???? zloy ? ???????? <http://lexa.cutenews.ru> / <_ ____,_-/\ __
- ---------------------------------------------------------/___/_____ \--'\|/----
- \/|*/
- abstract class SQL_Control extends SQL_Vars implements Countable {
-
- ////////////////////////////////////////////////////////////////////////////////
-
- function create(){
- $query = self::query($this->build('create'))->exec();
-
- if ($query === null)
- return 0;
-
- $result = self::alter();
- return ($result === 0 ? 1 : $result);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- function alter(){
- if (!$query = $this->build('alter'))
- return 0;
-
- cache::remove('sql/schema/'.$this->table.'.php');
- return self::query($query)->exec();
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- function save($full = false){
- $result = array();
-
- self::_check();
- self::_save($result);
-
- if (!array_key_exists($this->alias, $result))
- $result = array($this->alias => array(0)) + $result;
-
- if ($full)
- return $result;
-
- self::_fetch_col($result = $result[$this->alias]);
- return reset($result);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- protected function _check(){
- if ($this->into){
- foreach ($this->values as $k => $v)
- if (!check::is_valid($this->check, array_combine($this->into, $v)))
- throw new Check_Except($this->check, $this->alias);
- } elseif (!check::is_valid($this->check, $this->values)){
- throw new Check_Except($this->check, $this->alias);
- }
-
- foreach ($this->parallel as $class)
- if ($class instanceof SQL)
- $class->_check();
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- protected function _save(&$result, $is_parallel = false){
- $values = $this->values;
- $belongs = array();
-
- foreach ($values as $k => $v)
- if (self::_is_HABTM($k)){
- $v = array_unique($v);
- sort($v);
- unset($values[$k]);
-
- if (self::$cache[$this->alias][$k] != $v)
- $belongs[substr($k, 0, -4)] = $v;
- } elseif ($k[0] == '#' and $result[$v]){
- $first = array_shift($result[$v]);
- $values[substr($k, 1)] = $first;
- $result[$v][] = $first;
- unset($values[$k]);
-
- if (
- !$this->where and !$this->relations['#'] and
- $result[$this->alias] and $result[$this->alias][0]
- )
- $this->where($this->primary_key.' = ?d', $result[$this->alias][0]);
- }
-
- if ($values){
if (!$this->where){
if (!$into = $this->into){
$into = array_keys($values);
- $values = array(array_values($values));
- }
-
- $args = array_merge(array($into), $values, $this->placeholders);
- $count = self::query($this->build('insert'), $args)->exec();
-
- if ($count !== null){
- $id = self::$connection['link']->lastInsertId();
- $result[$this->alias][] = (int)$id;
-
- if ($id and b::len($values) > 1)
- $result[$this->alias] = array_merge(
- $result[$this->alias],
- range(($id + 1), ($id + $count - 1))
- );
- } else {
$result[$this->alias][] = $count;
}
- } else {
- $args = array_merge(array($values), $this->placeholders);
- $result[$this->alias][] = self::query($this->build('update'), $args)->exec();
- }
-
- if (end($result[$this->alias]) === null)
- return;
- }
-
- foreach ($belongs as $k => $v){
- $local = $this->relations[$k]['local'];
- $foreign = $this->relations[$k]['foreign'];
-
- $class = self::table($foreign['alias1']);
- $id = ($this->id ? $this->id : $result[$local['alias']][0]);
-
- $class->where($foreign['field1'].' = ?', $id)->delete();
- $class->where = array();
-
- foreach ($v as $i)
- $class->values(array(
- $foreign['field1'] => $id,
- $foreign['field3'] => $i
- ));
-
- $this->parallel[] = $class;
- }
-
- foreach ($this->parallel as $class)
- if ($class instanceof SQL)
- $class->_save($result, true);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- function delete(){
- $from = $this->from;
-
- foreach ($this->from as $k => $v)
- if ($pos = stripos($v, ' as '))
- $from[$k] = trim(substr($v, 0, $pos));
-
- return self::query($this->build('delete'))->exec();
-
- $args = $this->placeholders;
- array_unshift($args, $this->build('delete'), $from, ($this->limit ? self::SKIP : $from));
- return call_user_func_array(array(self::$connection, 'query'), $args);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- function fetch(){
- if (!$this->select)
- $this->select[] = '*';
-
- $query = $this->build('select');
- $self = clone $this;
-
- if ($this->multiple and !$this->group_by and ($this->limit or $this->where)){
- $class = clone $this;
- $class->select = $class->group_by = array($this->primary_key);
- $class->join = array();
-
- if (!$ids = $class->query($class->build('select'))->fetch_col())
- return array();
-
- $self->where = $self->placeholders = array();
- $self->having = array();
- $self->limit = $self->offset = 0;
-
- $self->where_between($this->primary_key, $ids);
- $query = $self->build('select');
- }
-
- return $self->query($query)->fetch();
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- function fetch_array(){
- $class = clone $this;
-
- if (!$this->select)
- $class->select[] = '*';
-
- $this->build('select');
-
- if ($multiple = array_unique($this->multiple)){
$class->select[] = $this->primary_key.' as __';
-
- foreach ($multiple as $k => $v){
- $vars = self::vars(inflector::singular(end(explode('.', $v))));
- $field = $v.'.'.($vars['primary_key'] ? $vars['primary_key'] : 'id');
- $class->select[] = $field.' as __'.$v;
- }
- }
-
- if (!$array = $class->fetch())
- return array();
-
- if (!$multiple){
- $result = arr::assoc($array);
- return ($this->id ? $result[0] : $result);
- }
-
- $result = $repl = $values = array();
- $func = create_function('$a, $b', 'return (substr_count($a, ".") < substr_count($b, "."));');
-
- foreach ($array as $row){
$i = $row['__'];
- unset($row['__']);
-
- if (!isset($result[$i]))
- $result[$i] = array();
-
- foreach ($row as $k => $v)
- if (substr($k, 0, 2) == '__'){
- unset($row[$k]);
-
- if ($v !== null){
$key = substr($k, 2);
- $repl[$key] = $key.'.'.$v;
- }
- } elseif ($v === null){
unset($row[$k]);
}
-
- uasort($repl, $func);
-
- foreach ($row as $k => $v){
$key = str_replace(array_keys($repl), array_values($repl), $k);
- $row[$key] = $v;
-
- if (
- ($pos = strrpos($k, '.')) and
- isset($repl[$key = substr($k, 0, $pos)])
- )
unset($row[$k]);
- }
-
- $result[$i] += $row;
- }
-
- $result = self::_fetch_array(arr::assoc($result));
- $result = array_values($result);
- return ($this->id ? $result[0] : $result);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- protected static function _fetch_array($array){
- $result = array();
-
- foreach ($array as $k => $v){
- if (is_array($v))
- $v = self::_fetch_array(is_int(key($v)) ? array_values($v) : $v);
-
- $result[$k] = $v;
- }
-
- return $result;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- function fetch_cell(){
- if (is_array($array = self::fetch_col()))
- return reset($array);
-
- return $array;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- function fetch_col(){
- $array = self::fetch();
- self::_fetch_col($array);
-
- return ($array ? $array : array());
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- protected static function _fetch_col(&$v){
- if (!is_array($cell = reset($v)))
- $v = $cell;
- else
- array_walk($v, array('self', '_fetch_col'));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- function fetch_row(){
- if ($array = reset(self::fetch()))
- return $array;
-
- return array();
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- function count(){
- $class = clone $this;
-
- $class->select = array('count(*)');
- $class->join = $class->order_by = array();
- $class->group_by = ($class->group_by ? $class->group_by : array($this->primary_key));
- $class->limit = $class->offset = 0;
-
- return array_sum($class->fetch_col());
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- function exists(){
if (!$this->where)
- return;
-
- $class = self::table($this->alias);
- $class->select[] = 1;
- $class->where = $this->where;
- $class->having = $this->having;
- $class->limit = 1;
- $class->placeholders = $this->placeholders;
-
- return (bool)$class->fetch_cell();
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- function begin(){
- return self::$connection['link']->beginTransaction();
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- function commit(){
if (!self::$connection['link']->commit())
- throw new SQL_Except;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- function rollback(){
return self::$connection['link']->rollback();
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- }