# 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
    00015     final class SelectQuery
    00016         extends QuerySkeleton
    00017         implements Named, JoinCapableQuery, Aliased
    00018     {
    00019         private $distinct       = false;
    00020
    00021         private $name           = null;
    00022
    00023         private $joiner         = null;
    00024
    00025         private $limit          = null;
    00026         private $offset         = null;
    00027
    00028         private $fields         = array();
    00029
    00030         private $order          = null;
    00031
    00032         private $group          = array();
    00033
    00034         private $having         = null;
    00035
    00036         public function __construct()
    00037         {
    00038             $this->joiner = new Joiner();
    00039             $this->order = new OrderChain();
    00040         }
    00041
    00042         public function __clone()
    00043         {
    00044             $this->joiner = clone $this->joiner;
    00045             $this->order = clone $this->order;
    00046         }
    00047
    00048         public function hasAliasInside($alias)
    00049         {
    00050             return isset($this->aliases[$alias]);
    00051         }
    00052
    00053         public function getAlias()
    00054         {
    00055             return $this->name;
    00056         }
    00057
    00058         public function getName()
    00059         {
    00060             return $this->name;
    00061         }
    00062
    00066         public function setName($name)
    00067         {
    00068             $this->name = $name;
    00069             $this->aliases[$name] = true;
    00070
    00071             return $this;
    00072         }
    00073
    00077         public function distinct()
    00078         {
    00079             $this->distinct = true;
    00080             return $this;
    00081         }
    00082
    00083         public function isDistinct()
    00084         {
    00085             return $this->distinct;
    00086         }
    00087
    00091         public function unDistinct()
    00092         {
    00093             $this->distinct = false;
    00094             return $this;
    00095         }
    00096
    00097         public function hasJoinedTable($table)
    00098         {
    00099             return $this->joiner->hasJoinedTable($table);
    00100         }
    00101
    00105         public function join($table, LogicalObject $logic, $alias = null)
    00106         {
    00107             $this->joiner->join(new SQLJoin($table, $logic, $alias));
    00108             $this->aliases[$alias] = true;
    00109
    00110             return $this;
    00111         }
    00112
    00116         public function leftJoin($table, LogicalObject $logic, $alias = null)
    00117         {
    00118             $this->joiner->leftJoin(new SQLLeftJoin($table, $logic, $alias));
    00119             $this->aliases[$alias] = true;
    00120
    00121             return $this;
    00122         }
    00123
    00127         public function rightJoin($table, LogicalObject $logic, $alias = null)
    00128         {
    00129             $this->joiner->rightJoin(new SQLRightJoin($table, $logic, $alias));
    00130             $this->aliases[$alias] = true;
    00131
    00132             return $this;
    00133         }
    00134
    00138         public function setOrderChain(OrderChain $chain)
    00139         {
    00140             $this->order = $chain;
    00141
    00142             return $this;
    00143         }
    00144
    00148         public function orderBy($field, $table = null)
    00149         {
    00150             $this->order->add($this->makeOrder($field, $table));
    00151
    00152             return $this;
    00153         }
    00154
    00158         public function prependOrderBy($field, $table = null)
    00159         {
    00160             $this->order->prepend($this->makeOrder($field, $table));
    00161
    00162             return $this;
    00163         }
    00164
    00169         public function desc()
    00170         {
    00171             if (!$last = $this->order->getLast())
    00172                 throw new WrongStateException('no fields to sort');
    00173
    00174             $last->desc();
    00175
    00176             return $this;
    00177         }
    00178
    00183         public function asc()
    00184         {
    00185             if (!$last = $this->order->getLast())
    00186                 throw new WrongStateException('no fields to sort');
    00187
    00188             $last->asc();
    00189
    00190             return $this;
    00191         }
    00192
    00196         public function groupBy($field, $table = null)
    00197         {
    00198             if ($field instanceof DialectString)
    00199                 $this->group[] = $field;
    00200             else
    00201                 $this->group[] =
    00202                     new DBField($field, $this->getLastTable($table));
    00203
    00204             return $this;
    00205         }
    00206
    00210         public function dropGroupBy()
    00211         {
    00212             $this->group = array();
    00213             return $this;
    00214         }
    00215
    00219         public function having(LogicalObject $exp)
    00220         {
    00221             $this->having = $exp;
    00222
    00223             return $this;
    00224         }
    00225
    00226         public function getLimit()
    00227         {
    00228             return $this->limit;
    00229         }
    00230
    00231         public function getOffset()
    00232         {
    00233             return $this->offset;
    00234         }
    00235
    00240         public function limit($limit = null, $offset = null)
    00241         {
    00242             if ($limit !== null)
    00243                 Assert::isPositiveInteger($limit, 'invalid limit specified');
    00244
    00245             if ($offset !== null)
    00246                 Assert::isInteger($offset, 'invalid offset specified');
    00247
    00248             $this->limit = $limit;
    00249             $this->offset = $offset;
    00250
    00251             return $this;
    00252         }
    00253
    00257         public function from($table, $alias = null)
    00258         {
    00259             $this->joiner->from(new FromTable($table, $alias));
    00260
    00261             $this->aliases[$alias] = true;
    00262
    00263             return $this;
    00264         }
    00265
    00266         public function getFirstTable()
    00267         {
    00268             return $this->joiner->getFirstTable();
    00269         }
    00270
    00275         public function get($field, $alias = null)
    00276         {
    00277             $this->fields[] =
    00278                 $this->resolveSelectField(
    00279                     $field,
    00280                     $alias,
    00281                     $this->getLastTable()
    00282                 );
    00283
    00284             if ($alias = $this->resolveAliasByField($field, $alias)) {
    00285                 $this->aliases[$alias] = true;
    00286             }
    00287
    00288             return $this;
    00289         }
    00290
    00294         public function multiGet(/* ... */)
    00295         {
    00296             $size = func_num_args();
    00297
    00298             if ($size && $args = func_get_args())
    00299                 for ($i = 0; $i < $size; ++$i)
    00300                     $this->get($args[$i]);
    00301
    00302             return $this;
    00303         }
    00304
    00308         public function arrayGet($array, $prefix = null)
    00309         {
    00310             $size = count($array);
    00311
    00312             if ($prefix) {
    00313                 for ($i = 0; $i < $size; ++$i) {
    00314                     if ($array[$i] instanceof DialectString) {
    00315                         if ($array[$i] instanceof DBField) {
    00316                             $alias = $prefix.$array[$i]->getField();
    00317                         } else {
    00318                             if ($array[$i] instanceof SQLFunction) {
    00319                                 $alias =
    00320                                     $array[$i]->setAlias(
    00321                                         $prefix.$array[$i]->getName()
    00322                                     )->
    00323                                     getAlias();
    00324                             } else {
    00325                                 $alias = $array[$i];
    00326                             }
    00327                         }
    00328                     } else {
    00329                         $alias = $prefix.$array[$i];
    00330                     }
    00331
    00332                     $this->get($array[$i], $alias);
    00333                 }
    00334             } else {
    00335                 for ($i = 0; $i < $size; ++$i) {
    00336                     $this->get($array[$i]);
    00337                 }
    00338             }
    00339
    00340             return $this;
    00341         }
    00342
    00343         public function getFieldsCount()
    00344         {
    00345             return count($this->fields);
    00346         }
    00347
    00348         public function getTablesCount()
    00349         {
    00350             return $this->joiner->getTablesCount();
    00351         }
    00352
    00353         public function getFieldNames()
    00354         {
    00355             $nameList = array();
    00356
    00357             foreach ($this->fields as $field) {
    00358                 if ($field instanceof SelectField)
    00359                     if ($alias = $field->getAlias()) {
    00360                         $nameList[] = $alias;
    00361                         continue;
    00362                     }
    00363
    00364                 $nameList[] = $field->getName();
    00365             }
    00366
    00367             return $nameList;
    00368         }
    00369
    00370         public function returning($field, $alias = null)
    00371         {
    00372             throw new UnsupportedMethodException();
    00373         }
    00374
    00375         public function toDialectString(Dialect $dialect)
    00376         {
    00377             $fieldList = array();
    00378
    00379             foreach ($this->fields as $field)
    00380                 $fieldList[] = $this->toDialectStringField($field, $dialect);
    00381
    00382             $query =
    00383                 'SELECT '.($this->distinct ? 'DISTINCT ' : null)
    00384                 .implode(', ', $fieldList)
    00385                 .$this->joiner->toDialectString($dialect);
    00386
    00387             // WHERE
    00388             $query .= parent::toDialectString($dialect);
    00389
    00390             if ($this->group) {
    00391                 $groupList = array();
    00392
    00393                 foreach ($this->group as $group)
    00394                     $groupList[] = $group->toDialectString($dialect);
    00395
    00396                 if ($groupList)
    00397                     $query .= ' GROUP BY '.implode(', ', $groupList);
    00398             }
    00399
    00400             if ($this->having)
    00401                 $query .= ' HAVING '.$this->having->toDialectString($dialect);
    00402
    00403             if ($this->order->getCount()) {
    00404                 $query .= ' ORDER BY '.$this->order->toDialectString($dialect);
    00405             }
    00406
    00407             if ($this->limit)
    00408                 $query .= ' LIMIT '.$this->limit;
    00409
    00410             if ($this->offset)
    00411                 $query .= ' OFFSET '.$this->offset;
    00412
    00413             return $query;
    00414         }
    00415
    00419         public function dropFields()
    00420         {
    00421             $this->fields = array();
    00422             return $this;
    00423         }
    00424
    00428         public function dropOrder()
    00429         {
    00430             $this->order = new OrderChain();
    00431             return $this;
    00432         }
    00433
    00437         public function dropLimit()
    00438         {
    00439             $this->limit = $this->offset = null;
    00440             return $this;
    00441         }
    00442
    00443         private function getLastTable($table = null)
    00444         {
    00445             if (!$table && ($last = $this->joiner->getLastTable()))
    00446                 return $last;
    00447
    00448             return $table;
    00449         }
    00450
    00454         private function makeOrder($field, $table = null)
    00455         {
    00456             if (
    00457                 $field instanceof OrderBy
    00458                 || $field instanceof DialectString
    00459             )
    00460                 return $field;
    00461             else
    00462                 return
    00463                     new OrderBy(
    00464                         new DBField($field, $this->getLastTable($table))
    00465                     );
    00466         }
    00467     }
    00468 ?>