onPHP

core/OSQL/SelectQuery.class.php Source File

 

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 /* $Id: SelectQuery.class.php 4790 2008-01-21 00:27:27Z voxus $ */
00012 
00016     final class SelectQuery
00017         extends QuerySkeleton
00018         implements Named, JoinCapableQuery, Aliased
00019     {
00020         private $distinct       = false;
00021         
00022         private $name           = null;
00023         
00024         private $joiner         = null;
00025         
00026         private $limit          = null;
00027         private $offset         = null;
00028         
00029         private $fields         = array();
00030         
00031         private $order          = null;
00032         
00033         private $group          = array();
00034         
00035         private $having         = null;
00036         
00037         private $aliases        = array();
00038         
00039         public function __construct()
00040         {
00041             $this->joiner = new Joiner();
00042             $this->order = new OrderChain();
00043         }
00044         
00045         public function __clone()
00046         {
00047             $this->joiner = clone $this->joiner;
00048             $this->order = clone $this->order;
00049         }
00050         
00051         public function hasAliasInside($alias)
00052         {
00053             return isset($this->aliases[$alias]);
00054         }
00055         
00056         public function getAlias()
00057         {
00058             return $this->name;
00059         }
00060         
00061         public function getName()
00062         {
00063             return $this->name;
00064         }
00065         
00069         public function setName($name)
00070         {
00071             $this->name = $name;
00072             $this->aliases[$name] = true;
00073             
00074             return $this;
00075         }
00076         
00080         public function distinct()
00081         {
00082             $this->distinct = true;
00083             return $this;
00084         }
00085         
00086         public function isDistinct()
00087         {
00088             return $this->distinct;
00089         }
00090         
00094         public function unDistinct()
00095         {
00096             $this->distinct = false;
00097             return $this;
00098         }
00099         
00100         public function hasJoinedTable($table)
00101         {
00102             return $this->joiner->hasJoinedTable($table);
00103         }
00104         
00108         public function join($table, LogicalObject $logic, $alias = null)
00109         {
00110             $this->joiner->join(new SQLJoin($table, $logic, $alias));
00111             $this->aliases[$alias] = true;
00112             
00113             return $this;
00114         }
00115         
00119         public function leftJoin($table, LogicalObject $logic, $alias = null)
00120         {
00121             $this->joiner->leftJoin(new SQLLeftJoin($table, $logic, $alias));
00122             $this->aliases[$alias] = true;
00123             
00124             return $this;
00125         }
00126         
00130         public function setOrderChain(OrderChain $chain)
00131         {
00132             $this->order = $chain;
00133             
00134             return $this;
00135         }
00136         
00140         public function orderBy($field, $table = null)
00141         {
00142             $this->order->add($this->makeOrder($field, $table));
00143             
00144             return $this;
00145         }
00146         
00150         public function prependOrderBy($field, $table = null)
00151         {
00152             $this->order->prepend($this->makeOrder($field, $table));
00153             
00154             return $this;
00155         }
00156         
00161         public function desc()
00162         {
00163             if (!$last = $this->order->getLast())
00164                 throw new WrongStateException('no fields to sort');
00165             
00166             $last->desc();
00167             
00168             return $this;
00169         }
00170         
00175         public function asc()
00176         {
00177             if (!$last = $this->order->getLast())
00178                 throw new WrongStateException('no fields to sort');
00179             
00180             $last->asc();
00181             
00182             return $this;
00183         }
00184         
00188         public function groupBy($field, $table = null)
00189         {
00190             if ($field instanceof DialectString)
00191                 $this->group[] = $field;
00192             else
00193                 $this->group[] =
00194                     new DBField($field, $this->getLastTable($table));
00195             
00196             return $this;
00197         }
00198         
00202         public function having(LogicalObject $exp)
00203         {
00204             $this->having = $exp;
00205             
00206             return $this;
00207         }
00208         
00209         public function getLimit()
00210         {
00211             return $this->limit;
00212         }
00213         
00214         public function getOffset()
00215         {
00216             return $this->offset;
00217         }
00218         
00223         public function limit($limit = null, $offset = null)
00224         {
00225             if ($limit !== null)
00226                 Assert::isPositiveInteger($limit, 'invalid limit specified');
00227                 
00228             if ($offset !== null)
00229                 Assert::isInteger($offset, 'invalid offset specified');
00230             
00231             $this->limit = $limit;
00232             $this->offset = $offset;
00233             
00234             return $this;
00235         }
00236         
00240         public function from($table, $alias = null)
00241         {
00242             $this->joiner->from(new FromTable($table, $alias));
00243             
00244             $this->aliases[$alias] = true;
00245             
00246             return $this;
00247         }
00248         
00255         public function get($field, $alias = null)
00256         {
00257             $table = null;
00258             if (is_object($field)) {
00259                 if (
00260                     ($field instanceof DBField)
00261                     && ($field->getTable() === null)
00262                 ) {
00263                     $this->fields[] = new SelectField(
00264                         $field->setTable($this->getLastTable()),
00265                         $alias
00266                     );
00267                 } elseif ($field instanceof SelectQuery) {
00268                     $this->fields[] = $field;
00269                     $this->aliases[$field->getAlias()] = true;
00270                 } elseif ($field instanceof DialectString) {
00271                     $this->fields[] = new SelectField($field, $alias);
00272                     
00273                     if ($field instanceof Aliased)
00274                         $this->aliases[$field->getAlias()] = true;
00275                     elseif ($alias)
00276                         $this->aliases[$alias] = true;
00277                 } else
00278                     throw new WrongArgumentException('unknown field type');
00279                 
00280                 return $this;
00281                 
00282             } elseif (false !== strpos($field, '*'))
00283                 throw new WrongArgumentException(
00284                     'do not fsck with us: specify fields explicitly'
00285                 );
00286             elseif (false !== strpos($field, '.'))
00287                 throw new WrongArgumentException(
00288                     'forget about dot: use DBField'
00289                 );
00290             else
00291                 $fieldName = $field;
00292             
00293             $this->fields[] = new SelectField(
00294                 new DBField($fieldName, $this->getLastTable($table)), $alias
00295             );
00296             
00297             $this->aliases[$alias] = true;
00298             
00299             return $this;
00300         }
00301         
00305         public function multiGet(/* ... */)
00306         {
00307             $size = func_num_args();
00308         
00309             if ($size && $args = func_get_args())
00310                 for ($i = 0; $i < $size; ++$i)
00311                     $this->get($args[$i]);
00312         
00313             return $this;
00314         }
00315         
00319         public function arrayGet($array, $prefix = null)
00320         {
00321             $size = count($array);
00322             
00323             if ($prefix) {
00324                 for ($i = 0; $i < $size; ++$i) {
00325                     if ($array[$i] instanceof DialectString) {
00326                         if ($array[$i] instanceof DBField) {
00327                             $alias = $prefix.$array[$i]->getField();
00328                         } else {
00329                             if ($array[$i] instanceof SQLFunction) {
00330                                 $alias =
00331                                     $array[$i]->setAlias(
00332                                         $prefix.$array[$i]->getName()
00333                                     )->
00334                                     getAlias();
00335                             } else {
00336                                 $alias = $array[$i];
00337                             }
00338                         }
00339                     } else {
00340                         $alias = $prefix.$array[$i];
00341                     }
00342                     
00343                     $this->get($array[$i], $alias);
00344                 }
00345             } else {
00346                 for ($i = 0; $i < $size; ++$i) {
00347                     $this->get($array[$i]);
00348                 }
00349             }
00350             
00351             return $this;
00352         }
00353         
00354         public function getFieldsCount()
00355         {
00356             return count($this->fields);
00357         }
00358         
00359         public function getTablesCount()
00360         {
00361             return $this->joiner->getTablesCount();
00362         }
00363         
00364         public function getFieldNames()
00365         {
00366             $nameList = array();
00367             
00368             foreach ($this->fields as $field) {
00369                 if ($field instanceof SelectField)
00370                     if ($alias = $field->getAlias()) {
00371                         $nameList[] = $alias;
00372                         continue;
00373                     }
00374                 
00375                 $nameList[] = $field->getName();
00376             }
00377             
00378             return $nameList;
00379         }
00380         
00381         public function toDialectString(Dialect $dialect)
00382         {
00383             $fieldList = array();
00384             foreach ($this->fields as $field) {
00385                 
00386                 if ($field instanceof SelectQuery) {
00387                     
00388                     Assert::isTrue(
00389                         null !== $alias = $field->getName(),
00390                         'can not use SelectQuery without name as get field'
00391                     );
00392                     
00393                     $fieldList[] =
00394                         "({$field->toDialectString($dialect)}) AS ".
00395                         $dialect->quoteField($alias);
00396                 } else
00397                     $fieldList[] = $field->toDialectString($dialect);
00398             }
00399             
00400             $query =
00401                 'SELECT '.($this->distinct ? 'DISTINCT ' : null)
00402                 .implode(', ', $fieldList)
00403                 .$this->joiner->toDialectString($dialect);
00404                 
00405             // WHERE
00406             $query .= parent::toDialectString($dialect);
00407             
00408             if ($this->group) {
00409                 $groupList = array();
00410                 
00411                 foreach ($this->group as $group)
00412                     $groupList[] = $group->toDialectString($dialect);
00413                 
00414                 if ($groupList)
00415                     $query .= ' GROUP BY '.implode(', ', $groupList);
00416             }
00417             
00418             if ($this->having)
00419                 $query .= ' HAVING '.$this->having->toDialectString($dialect);
00420             
00421             if ($this->order->getCount()) {
00422                 $query .= ' ORDER BY '.$this->order->toDialectString($dialect);
00423             }
00424             
00425             if ($this->limit)
00426                 $query .= ' LIMIT '.$this->limit;
00427             
00428             if ($this->offset)
00429                 $query .= ' OFFSET '.$this->offset;
00430             
00431             return $query;
00432         }
00433         
00437         public function dropFields()
00438         {
00439             $this->fields = array();
00440             return $this;
00441         }
00442         
00446         public function dropOrder()
00447         {
00448             $this->order = new OrderChain();
00449             return $this;
00450         }
00451         
00452         private function getLastTable($table = null)
00453         {
00454             if (!$table && ($last = $this->joiner->getLastTable()))
00455                 return $last;
00456             
00457             return $table;
00458         }
00459         
00463         private function makeOrder($field, $table = null)
00464         {
00465             if (
00466                 $field instanceof OrderBy
00467                 || $field instanceof DialectString
00468             )
00469                 return $field;
00470             else
00471                 return
00472                     new OrderBy(
00473                         new DBField($field, $this->getLastTable($table))
00474                     );
00475         }
00476     }
00477 ?>

generated by doxygen-1.5.4
for onPHP at Mon Jan 21 03:38:29 2008