Ejemplo n.º 1
0
 protected function column_alias_sql(Dao $dao, Column $column, Q $q, $alias = true)
 {
     $column_str = $alias ? $column->table_alias() . '.' . $this->quotation($column->column()) : $this->quotation($column->column());
     if ($q->ignore_case()) {
         return 'upper(' . $column_str . ')';
     }
     return $column_str;
 }
Ejemplo n.º 2
0
 protected final function __new__()
 {
     if (func_num_args() == 1) {
         foreach (func_get_arg(0) as $n => $v) {
             switch ($n) {
                 case '_has_hierarchy_':
                 case '_class_id_':
                 case '_hierarchy_':
                     $this->{$n} = $v;
                     break;
                 default:
             }
         }
     }
     $p = get_class($this);
     if (!isset($this->_class_id_)) {
         $this->_class_id_ = $p;
     }
     if (isset(self::$_dao_[$this->_class_id_])) {
         foreach (self::$_dao_[$this->_class_id_]->_has_dao_ as $name => $dao) {
             $this->{$name}($dao);
         }
         return;
     }
     if (!isset(self::$_co_anon_[$p])) {
         $readonly = static::anon('readonly', false);
         $anon = array(static::anon('database'), static::anon('table'), static::anon('create', !$readonly) === true, static::anon('update', !$readonly) === true, static::anon('delete', !$readonly) === true, null, false, false);
         if (empty($anon[0])) {
             $conf = explode("\\", $p);
             $def = \org\rhaco\Conf::get('connection');
             while (!isset($def[implode('.', $conf)]) && !empty($conf)) {
                 array_pop($conf);
             }
             if (empty($conf) && !isset($def['*'])) {
                 throw new \org\rhaco\store\db\exception\DaoConnectionException('could not find the connection settings `' . $p . '`');
             }
             $anon[0] = empty($conf) ? '*' : implode('.', $conf);
         }
         if (empty($anon[1])) {
             $table_class = $p;
             $parent_class = get_parent_class($p);
             $ref = new \ReflectionClass($parent_class);
             while (true) {
                 $ref = new \ReflectionClass($parent_class);
                 if (__CLASS__ == $parent_class || $ref->isAbstract()) {
                     break;
                 }
                 $table_class = $parent_class;
                 $parent_class = get_parent_class($parent_class);
             }
             $table_class = preg_replace("/^.*\\\\(.+)\$/", "\\1", $table_class);
             $anon[1] = strtolower($table_class[0]);
             for ($i = 1; $i < strlen($table_class); $i++) {
                 $anon[1] .= ctype_lower($table_class[$i]) ? $table_class[$i] : '_' . strtolower($table_class[$i]);
             }
         }
         $config = self::get_con($anon[0], $p);
         if (!isset(self::$_connections_[$anon[0]])) {
             throw new \RuntimeException('connection fail ' . str_replace("\\", '.', get_class($this)));
         }
         static::set_module(self::$_connections_[$anon[0]]->connection_module());
         $anon[5] = isset($config['prefix']) ? $config['prefix'] : '';
         $anon[6] = isset($config['upper']) && $config['upper'] === true;
         $anon[7] = isset($config['lower']) && $config['lower'] === true;
         self::$_co_anon_[$p] = $anon;
         self::$_co_anon_[$p][1] = self::set_table_name(self::$_co_anon_[$p][1], $p);
     }
     $has_hierarchy = isset($this->_hierarchy_) ? $this->_hierarchy_ - 1 : $this->_has_hierarchy_;
     $root_table_alias = 't' . self::$_cnt_++;
     $_columns_ = $_self_columns_ = $_where_columns_ = $_conds_ = $_join_conds_ = $_alias_ = $_has_many_conds_ = $_has_dao_ = array();
     $prop = $last_cond_column = array();
     $ref = new \ReflectionClass($this);
     foreach ($ref->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED) as $prop) {
         $props[] = $prop->getName();
     }
     while (!empty($props)) {
         $name = array_shift($props);
         if ($name[0] != '_' && $this->prop_anon($name, 'extra') !== true) {
             $anon_cond = $this->prop_anon($name, 'cond');
             $column_type = $this->prop_anon($name, 'type');
             $column = new Column();
             $column->name($name);
             $column->column($this->prop_anon($name, 'column', $name));
             $column->column_alias('c' . self::$_cnt_++);
             if ($anon_cond === null) {
                 if (ctype_upper($column_type[0]) && class_exists($column_type) && is_subclass_of($column_type, __CLASS__)) {
                     throw new \RuntimeException('undef ' . $name . ' annotation `cond`');
                 }
                 $column->table($this->table());
                 $column->table_alias($root_table_alias);
                 $column->primary($this->prop_anon($name, 'primary', false));
                 $column->auto($column_type === 'serial');
                 $_columns_[] = $column;
                 $_self_columns_[$name] = $column;
                 $_alias_[$column->column_alias()] = $name;
             } else {
                 if (false !== strpos($anon_cond, '(')) {
                     $is_has = class_exists($column_type) && is_subclass_of($column_type, __CLASS__);
                     $is_has_many = $is_has && $this->prop_anon($name, 'attr') === 'a';
                     if ((!$is_has || $has_hierarchy > 0) && preg_match("/^(.+)\\((.*)\\)(.*)\$/", $anon_cond, $match)) {
                         list(, $self_var, $conds_string, $has_var) = $match;
                         $conds = array();
                         $ref_table = $ref_table_alias = null;
                         if (!empty($conds_string)) {
                             foreach (explode(',', $conds_string) as $key => $cond) {
                                 $tcc = explode('.', $cond, 3);
                                 switch (sizeof($tcc)) {
                                     case 1:
                                         $conds[] = Column::cond_instance($tcc[0], 'c' . self::$_cnt_++, $this->table(), $root_table_alias);
                                         break;
                                     case 2:
                                         list($t, $c1) = $tcc;
                                         $ref_table = self::set_table_name($t, $p);
                                         $ref_table_alias = 't' . self::$_cnt_++;
                                         $conds[] = Column::cond_instance($c1, 'c' . self::$_cnt_++, $ref_table, $ref_table_alias);
                                         break;
                                     case 3:
                                         list($t, $c1, $c2) = $tcc;
                                         $ref_table = self::set_table_name($t, $p);
                                         $ref_table_alias = 't' . self::$_cnt_++;
                                         $conds[] = Column::cond_instance($c1, 'c' . self::$_cnt_++, $ref_table, $ref_table_alias);
                                         $conds[] = Column::cond_instance($c2, 'c' . self::$_cnt_++, $ref_table, $ref_table_alias);
                                         break;
                                     default:
                                         throw new \LogicException('annotation error : `' . $name . '`');
                                 }
                             }
                         }
                         if ($is_has_many) {
                             if (empty($has_var)) {
                                 throw new \LogicException('annotation error : `' . $name . '`');
                             }
                             $dao = new $column_type(array('_class_id_' => $p . '___' . self::$_cnt_++));
                             $_has_many_conds_[$name] = array($dao, $has_var, $self_var);
                         } else {
                             $self_db = true;
                             if ($is_has) {
                                 if (empty($has_var)) {
                                     throw new \LogicException('annotation error : `' . $name . '`');
                                 }
                                 $dao = new $column_type(array('_class_id_' => $p . '___' . self::$_cnt_++, '_hierarchy_' => $has_hierarchy));
                                 $this->{$name}($dao);
                                 if ($dao->table() == $this->table()) {
                                     $_has_dao_[$name] = $dao;
                                     $_columns_ = array_merge($_columns_, $dao->columns());
                                     $_conds_ = array_merge($_conds_, $dao->conds());
                                     $this->prop_anon($name, 'has', true, true);
                                     foreach ($dao->columns() as $column) {
                                         $_alias_[$column->column_alias()] = $name;
                                     }
                                     $has_column = $dao->base_column($dao->columns(), $has_var);
                                     $conds[] = Column::cond_instance($has_column->column(), 'c' . self::$_cnt_++, $has_column->table(), $has_column->table_alias());
                                     array_unshift($conds, Column::cond_instance($self_var, 'c' . self::$_cnt_++, $this->table(), $root_table_alias));
                                 } else {
                                     $_has_many_conds_[$name] = array($dao, $has_var, $self_var);
                                     $self_db = false;
                                 }
                             } else {
                                 if ($self_var[0] == '@') {
                                     $cond_var = null;
                                     $cond_name = substr($self_var, 1);
                                     if (strpos($cond_name, '.') !== false) {
                                         list($cond_name, $cond_var) = explode('.', $cond_name);
                                     }
                                     if (!isset($last_cond_column[$cond_name]) && in_array($cond_name, $props)) {
                                         $props[] = $name;
                                         continue;
                                     }
                                     $cond_column = clone $last_cond_column[$cond_name];
                                     if (isset($cond_var)) {
                                         $cond_column->column($cond_var);
                                         $cond_column->column_alias('c' . self::$_cnt_++);
                                     }
                                     array_unshift($conds, $cond_column);
                                 } else {
                                     array_unshift($conds, Column::cond_instance($self_var, 'c' . self::$_cnt_++, $this->table(), $root_table_alias));
                                 }
                                 $column->table($ref_table);
                                 $column->table_alias($ref_table_alias);
                                 $_alias_[$column->column_alias()] = $name;
                                 if (!$this->prop_anon($name, 'join', false)) {
                                     $_columns_[] = $column;
                                 }
                                 $_where_columns_[$name] = $column;
                             }
                             if ($self_db) {
                                 if (sizeof($conds) % 2 != 0) {
                                     throw new \RuntimeException($name . '[' . $column_type . '] is illegal condition');
                                 }
                                 if ($this->prop_anon($name, 'join', false)) {
                                     $this->prop_anon($name, 'get', false, true);
                                     $this->prop_anon($name, 'set', false, true);
                                     for ($i = 0; $i < sizeof($conds); $i += 2) {
                                         $_join_conds_[$name][] = array($conds[$i], $conds[$i + 1]);
                                     }
                                 } else {
                                     for ($i = 0; $i < sizeof($conds); $i += 2) {
                                         $_conds_[] = array($conds[$i], $conds[$i + 1]);
                                     }
                                 }
                             }
                             if (!empty($conds)) {
                                 $cond_column = clone $conds[sizeof($conds) - 1];
                                 $cond_column->column($column->column());
                                 $cond_column->column_alias('c' . self::$_cnt_++);
                                 $last_cond_column[$name] = $cond_column;
                             }
                         }
                     }
                 } else {
                     if ($anon_cond[0] === '@') {
                         $cond_name = substr($anon_cond, 1);
                         if (in_array($cond_name, $props)) {
                             $props[] = $name;
                             continue;
                         }
                         $c = $this->base_column($_columns_, substr($anon_cond, 1));
                         $column->table($c->table());
                         $column->table_alias($c->table_alias());
                         $_columns_[] = $column;
                         $_where_columns_[$name] = $column;
                         $_alias_[$column->column_alias()] = $name;
                     }
                 }
             }
         }
     }
     self::$_dao_[$this->_class_id_] = (object) array('_columns_' => $_columns_, '_self_columns_' => $_self_columns_, '_where_columns_' => $_where_columns_, '_conds_' => $_conds_, '_join_conds_' => $_join_conds_, '_alias_' => $_alias_, '_has_dao_' => $_has_dao_, '_has_many_conds_' => $_has_many_conds_);
 }