SelectQuery.class.php

Go to the documentation of this file.
00001 <?php
00002 /****************************************************************************
00003  *   Copyright (C) 2004-2007 by Konstantin V. Arkhipov, Anton E. Lebedevich *
00004  *                                                                          *
00005  *   This program is free software; you can redistribute it and/or modify   *
00006  *   it under the terms of the GNU Lesser General Public License as         *
00007  *   published by the Free Software Foundation; either version 3 of the     *
00008  *   License, or (at your option) any later version.                        *
00009  *                                                                          *
00010  ****************************************************************************/
00011 
00012 /*
00013     $Id: SelectQuery.class.php 4687 2007-12-09 18:57:18Z voxus $
00014     
00015     06 Oct 2005: Skeleton merged back.
00016     
00017     07 Jun 2005: Separation of {get,set}ters.
00018     
00019     28 Mar 2005: Fourth rewrite by Anton.
00020     
00021     04 Jan 2005: Third rewrite. Main goal now - simplicity.
00022 */
00023 
00027     final class SelectQuery
00028         extends QuerySkeleton
00029         implements Named, JoinCapableQuery, Aliased
00030     {
00031         private $distinct       = false;
00032 
00033         private $name           = null;
00034         
00035         private $joiner         = null;
00036         
00038         private $strategyId     = null;
00039         
00040         private $limit          = null;
00041         private $offset         = null;
00042 
00043         private $fields         = array();
00044         
00045         private $order          = null;
00046         
00047         private $group          = array();
00048         
00049         private $having         = null;
00050         
00051         private $aliases        = array();
00052         
00053         public function __construct()
00054         {
00055             $this->joiner = new Joiner();
00056             $this->order = new OrderChain();
00057         }
00058         
00059         public function __clone()
00060         {
00061             $this->joiner = clone $this->joiner;
00062             $this->order = clone $this->order;
00063         }
00064         
00065         public function getFetchStrategyId()
00066         {
00067             return $this->strategyId;
00068         }
00069         
00073         public function setFetchStrategyId($id)
00074         {
00075             $this->strategyId = $id;
00076             
00077             return $this;
00078         }
00079         
00080         public function hasAliasInside($alias)
00081         {
00082             return isset($this->aliases[$alias]);
00083         }
00084         
00085         public function getAlias()
00086         {
00087             return $this->name;
00088         }
00089         
00090         public function getName()
00091         {
00092             return $this->name;
00093         }
00094         
00098         public function setName($name)
00099         {
00100             $this->name = $name;
00101             $this->aliases[$name] = true;
00102             
00103             return $this;
00104         }
00105 
00109         public function distinct()
00110         {
00111             $this->distinct = true;
00112             return $this;
00113         }
00114 
00115         public function isDistinct()
00116         {
00117             return $this->distinct;
00118         }
00119 
00123         public function unDistinct()
00124         {
00125             $this->distinct = false;
00126             return $this;
00127         }
00128         
00129         public function hasJoinedTable($table)
00130         {
00131             return $this->joiner->hasJoinedTable($table);
00132         }
00133 
00137         public function join($table, LogicalObject $logic, $alias = null)
00138         {
00139             $this->joiner->join(new SQLJoin($table, $logic, $alias));
00140             $this->aliases[$alias] = true;
00141             
00142             return $this;
00143         }
00144         
00148         public function leftJoin($table, LogicalObject $logic, $alias = null)
00149         {
00150             $this->joiner->leftJoin(new SQLLeftJoin($table, $logic, $alias));
00151             $this->aliases[$alias] = true;
00152             
00153             return $this;
00154         }
00155         
00159         public function setOrderChain(OrderChain $chain)
00160         {
00161             $this->order = $chain;
00162             
00163             return $this;
00164         }
00165 
00169         public function orderBy($field, $table = null)
00170         {
00171             $this->order->add($this->makeOrder($field, $table));
00172             
00173             return $this;
00174         }
00175         
00179         public function prependOrderBy($field, $table = null)
00180         {
00181             $this->order->prepend($this->makeOrder($field, $table));
00182 
00183             return $this;
00184         }
00185 
00190         public function desc()
00191         {
00192             if (!$last = $this->order->getLast())
00193                 throw new WrongStateException('no fields to sort');
00194 
00195             $last->desc();
00196 
00197             return $this;
00198         }
00199         
00204         public function asc()
00205         {
00206             if (!$last = $this->order->getLast())
00207                 throw new WrongStateException('no fields to sort');
00208 
00209             $last->asc();
00210 
00211             return $this;
00212         }
00213 
00217         public function groupBy($field, $table = null)
00218         {
00219             if ($field instanceof DialectString)
00220                 $this->group[] = $field;
00221             else
00222                 $this->group[] =
00223                     new DBField($field, $this->getLastTable($table));
00224 
00225             return $this;
00226         }
00227         
00231         public function having(LogicalObject $exp)
00232         {
00233             $this->having = $exp;
00234             
00235             return $this;
00236         }
00237         
00238         public function getLimit()
00239         {
00240             return $this->limit;
00241         }
00242         
00243         public function getOffset()
00244         {
00245             return $this->offset;
00246         }
00247 
00252         public function limit($limit = null, $offset = null)
00253         {
00254             if ($limit !== null)
00255                 Assert::isPositiveInteger($limit, 'invalid limit specified');
00256                 
00257             if ($offset !== null)
00258                 Assert::isInteger($offset, 'invalid offset specified');
00259             
00260             $this->limit = $limit;
00261             $this->offset = $offset;
00262             
00263             return $this;
00264         }
00265 
00269         public function from($table, $alias = null)
00270         {
00271             $this->joiner->from(new FromTable($table, $alias));
00272             
00273             $this->aliases[$alias] = true;
00274 
00275             return $this;
00276         }
00277         
00284         public function get($field, $alias = null)
00285         {
00286             $table = null;
00287             if (is_object($field)) {
00288                 if (
00289                     ($field instanceof DBField)
00290                     && ($field->getTable() === null)
00291                 ) {
00292                     $this->fields[] = new SelectField(
00293                         $field->setTable($this->getLastTable()),
00294                         $alias
00295                     );
00296                 } elseif ($field instanceof SelectQuery) {
00297                     $this->fields[] = $field;
00298                     $this->aliases[$field->getAlias()] = true;
00299                 } elseif ($field instanceof DialectString) {
00300                     $this->fields[] = new SelectField($field, $alias);
00301                     
00302                     if ($field instanceof Aliased)
00303                         $this->aliases[$field->getAlias()] = true;
00304                     elseif ($alias)
00305                         $this->aliases[$alias] = true;
00306                 } else
00307                     throw new WrongArgumentException('unknown field type');
00308                 
00309                 return $this;
00310                 
00311             } elseif (false !== strpos($field, '*'))
00312                 throw new WrongArgumentException(
00313                     'do not fsck with us: specify fields explicitly'
00314                 );
00315             elseif (false !== strpos($field, '.'))
00316                 throw new WrongArgumentException(
00317                     'forget about dot: use DBField'
00318                 );
00319             else
00320                 $fieldName = $field;
00321             
00322             $this->fields[] = new SelectField(
00323                 new DBField($fieldName, $this->getLastTable($table)), $alias
00324             );
00325             
00326             $this->aliases[$alias] = true;
00327 
00328             return $this;
00329         }
00330         
00334         public function multiGet(/* ... */)
00335         {
00336             $size = func_num_args();
00337         
00338             if ($size && $args = func_get_args())
00339                 for ($i = 0; $i < $size; ++$i)
00340                     $this->get($args[$i]);
00341         
00342             return $this;
00343         }
00344         
00348         public function arrayGet($array, $prefix = null)
00349         {
00350             $size = count($array);
00351             
00352             if ($prefix) {
00353                 for ($i = 0; $i < $size; ++$i) {
00354                     if ($array[$i] instanceof DialectString) {
00355                         if ($array[$i] instanceof DBField) {
00356                             $alias = $prefix.$array[$i]->getField();
00357                         } else {
00358                             if ($array[$i] instanceof SQLFunction) {
00359                                 $alias =
00360                                     $array[$i]->setAlias(
00361                                         $prefix.$array[$i]->getName()
00362                                     )->
00363                                     getAlias();
00364                             } else {
00365                                 $alias = $array[$i];
00366                             }
00367                         }
00368                     } else {
00369                         $alias = $prefix.$array[$i];
00370                     }
00371 
00372                     $this->get($array[$i], $alias);
00373                 }
00374             } else {
00375                 for ($i = 0; $i < $size; ++$i) {
00376                     $this->get($array[$i]);
00377                 }
00378             }
00379                     
00380             return $this;
00381         }
00382 
00383         public function getFieldsCount()
00384         {
00385             return count($this->fields);
00386         }
00387         
00388         public function getTablesCount()
00389         {
00390             return $this->joiner->getTablesCount();
00391         }
00392         
00393         public function getFieldNames()
00394         {
00395             $nameList = array();
00396             
00397             foreach ($this->fields as $field) {
00398                 if ($field instanceof SelectField)
00399                     if ($alias = $field->getAlias()) {
00400                         $nameList[] = $alias;
00401                         continue;
00402                     }
00403                 
00404                 $nameList[] = $field->getName();
00405             }
00406             
00407             return $nameList;
00408         }
00409         
00410         public function toDialectString(Dialect $dialect)
00411         {
00412             $fieldList = array();
00413             foreach ($this->fields as $field) {
00414                 
00415                 if ($field instanceof SelectQuery) {
00416                     
00417                     Assert::isTrue(
00418                         null !== $alias = $field->getName(),
00419                         'can not use SelectQuery without name as get field'
00420                     );
00421                     
00422                     $fieldList[] =
00423                         "({$field->toDialectString($dialect)}) AS ".
00424                         $dialect->quoteField($alias);
00425                 } else
00426                     $fieldList[] = $field->toDialectString($dialect);
00427             }
00428 
00429             $query =
00430                 'SELECT '.($this->distinct ? 'DISTINCT ' : null)
00431                 .implode(', ', $fieldList)
00432                 .$this->joiner->toDialectString($dialect);
00433                 
00434             // WHERE
00435             $query .= parent::toDialectString($dialect);
00436 
00437             if ($this->group) {
00438                 $groupList = array();
00439                 
00440                 foreach ($this->group as $group)
00441                     $groupList[] = $group->toDialectString($dialect);
00442                 
00443                 if ($groupList)
00444                     $query .= " GROUP BY ".implode(', ', $groupList);
00445             }
00446             
00447             if ($this->having)
00448                 $query .= ' HAVING '.$this->having->toDialectString($dialect);
00449             
00450             if ($this->order->getCount()) {
00451                 $query .= ' ORDER BY '.$this->order->toDialectString($dialect);
00452             }
00453             
00454             if ($this->limit)
00455                 $query .= " LIMIT {$this->limit}";
00456             
00457             if ($this->offset)
00458                 $query .= " OFFSET {$this->offset}";
00459             
00460             return $query;
00461         }
00462         
00466         public function dropFields()
00467         {
00468             $this->fields = array();
00469             return $this;
00470         }
00471         
00475         public function dropOrder()
00476         {
00477             $this->order = new OrderChain();
00478             return $this;
00479         }
00480 
00481         private function getLastTable($table = null)
00482         {
00483             if (!$table && ($last = $this->joiner->getLastTable()))
00484                 return $last;
00485             
00486             return $table;
00487         }
00488         
00492         private function makeOrder($field, $table = null)
00493         {
00494             if (
00495                 $field instanceof OrderBy
00496                 || $field instanceof DialectString
00497             )
00498                 return $field;
00499             else
00500                 return
00501                     new OrderBy(
00502                         new DBField($field, $this->getLastTable($table))
00503                     );
00504         }
00505     }
00506 ?>

Generated on Sun Dec 9 21:56:23 2007 for onPHP by  doxygen 1.5.4