# OqlSelectParser.class.php

Go to the documentation of this file.

    00001 <?php
    00002 /****************************************************************************
    00003  *   Copyright (C) 2008 by Vladlen Y. Koshelev                              *
    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
    00032     final class OqlSelectParser extends OqlParser
    00033     {
    00034         // states
    00035         const PROPERTY_STATE    = 1;
    00036         const FROM_STATE        = 2;
    00037         const WHERE_STATE       = 3;
    00038         const GROUP_BY_STATE    = 4;
    00039         const ORDER_BY_STATE    = 5;
    00040         const HAVING_STATE      = 6;
    00041         const LIMIT_STATE       = 7;
    00042         const OFFSET_STATE      = 8;
    00043
    00047         public static function create()
    00048         {
    00049             return new self;
    00050         }
    00051
    00055         protected function makeOqlObject()
    00056         {
    00057             return OqlSelectQuery::create();
    00058         }
    00059
    00060         protected function handleState()
    00061         {
    00062             switch ($this->state) {
    00063                 case self::INITIAL_STATE:
    00064                 case self::PROPERTY_STATE:
    00065                     return $this->propertyState();
    00066
    00067                 case self::FROM_STATE:
    00068                     return $this->fromState();
    00069
    00070                 case self::WHERE_STATE:
    00071                     return $this->whereState();
    00072
    00073                 case self::GROUP_BY_STATE:
    00074                     return $this->groupByState();
    00075
    00076                 case self::ORDER_BY_STATE:
    00077                     return $this->orderByState();
    00078
    00079                 case self::HAVING_STATE:
    00080                     return $this->havingState();
    00081
    00082                 case self::LIMIT_STATE:
    00083                     return $this->limitState();
    00084
    00085                 case self::OFFSET_STATE:
    00086                     return $this->offsetState();
    00087             }
    00088
    00089             throw new WrongStateException('state machine is broken');
    00090         }
    00091
    00092         private function propertyState()
    00093         {
    00094             $token = $this->tokenizer->peek();
    00095
    00096             if (!$token)
    00097                 $this->error("expecting 'from' clause");
    00098
    00099             if ($this->checkKeyword($token, 'from'))
    00100                 return self::FROM_STATE;
    00101
    00102             $clause = OqlSelectPropertiesParser::create()->
    00103                 setTokenizer($this->tokenizer)->
    00104                 parse();
    00105
    00106             $this->oqlObject->addProperties($clause);
    00107             if ($clause->isDistinct())
    00108                 $this->oqlObject->setDistinct(true);
    00109
    00110             return self::FROM_STATE;
    00111         }
    00112
    00113         private function fromState()
    00114         {
    00115             if ($this->checkKeyword($this->tokenizer->peek(), 'from')) {
    00116                 $this->tokenizer->next();
    00117
    00118                 $class = $this->tokenizer->next();
    00119                 $className = $this->getTokenValue($class, true);
    00120
    00121                 if (
    00122                     !$this->checkIdentifier($class)
    00123                     || !ClassUtils::isClassName($className)
    00124                 ) {
    00125                     $this->error('invalid class name:', $className);
    00126                 }
    00127
    00128                 if (!class_exists($className, true))
    00129                     $this->error('class does not exists:', $className);
    00130
    00131                 if (!ClassUtils::isInstanceOf($className, 'DAOConnected'))
    00132                     $this->error('class must implement DAOConnected interface:', $className);
    00133
    00134                 $this->oqlObject->setDao(
    00135                     call_user_func(array($className, 'dao'))
    00136                 );
    00137
    00138             } else
    00139                 $this->error("expecting 'from' clause");
    00140
    00141             return self::WHERE_STATE;
    00142         }
    00143
    00144         private function whereState()
    00145         {
    00146             if ($this->checkKeyword($this->tokenizer->peek(), 'where')) {
    00147                 $this->tokenizer->next();
    00148
    00149                 $this->oqlObject->where(
    00150                     OqlWhereParser::create()->
    00151                         setTokenizer($this->tokenizer)->
    00152                         parse()
    00153                 );
    00154             }
    00155
    00156             return self::GROUP_BY_STATE;
    00157         }
    00158
    00159         private function groupByState()
    00160         {
    00161             if ($this->checkKeyword($this->tokenizer->peek(), 'group by')) {
    00162                 $this->tokenizer->next();
    00163
    00164                 $this->oqlObject->addGroupBy(
    00165                     OqlGroupByParser::create()->
    00166                         setTokenizer($this->tokenizer)->
    00167                         parse()
    00168                 );
    00169             }
    00170
    00171             return self::ORDER_BY_STATE;
    00172         }
    00173
    00174         private function orderByState()
    00175         {
    00176             if ($this->checkKeyword($this->tokenizer->peek(), 'order by')) {
    00177                 $this->tokenizer->next();
    00178
    00179                 $this->oqlObject->addOrderBy(
    00180                     OqlOrderByParser::create()->
    00181                         setTokenizer($this->tokenizer)->
    00182                         parse()
    00183                 );
    00184             }
    00185
    00186             return self::HAVING_STATE;
    00187         }
    00188
    00189         private function havingState()
    00190         {
    00191             if ($this->checkKeyword($this->tokenizer->peek(), 'having')) {
    00192                 $this->tokenizer->next();
    00193
    00194                 $this->oqlObject->addHaving(
    00195                     OqlHavingParser::create()->
    00196                         setTokenizer($this->tokenizer)->
    00197                         parse()
    00198                 );
    00199             }
    00200
    00201             return self::LIMIT_STATE;
    00202         }
    00203
    00204         private function limitState()
    00205         {
    00206             if ($this->checkKeyword($this->tokenizer->peek(), 'limit')) {
    00207                 $this->tokenizer->next();
    00208
    00209                 $token = $this->tokenizer->next();
    00210                 if (
    00211                     $this->checkToken($token, OqlToken::NUMBER)
    00212                     || $this->checkToken($token, OqlToken::SUBSTITUTION)
    00213                 ) {
    00214                     $this->oqlObject->setLimit(
    00215                         $this->makeQueryParameter($token)
    00216                     );
    00217
    00218                 } else {
    00219                     $this->error("expecting 'limit' expression");
    00220                 }
    00221             }
    00222
    00223             return self::OFFSET_STATE;
    00224         }
    00225
    00226         private function offsetState()
    00227         {
    00228             if ($this->checkKeyword($this->tokenizer->peek(), 'offset')) {
    00229                 $this->tokenizer->next();
    00230
    00231                 $token = $this->tokenizer->next();
    00232                 if (
    00233                     $this->checkToken($token, OqlToken::NUMBER)
    00234                     || $this->checkToken($token, OqlToken::SUBSTITUTION)
    00235                 ) {
    00236                     $this->oqlObject->setOffset(
    00237                         $this->makeQueryParameter($token)
    00238                     );
    00239
    00240                 } else {
    00241                     $this->error("expecting 'offset' expression");
    00242                 }
    00243             }
    00244
    00245             if ($token = $this->tokenizer->peek())
    00246                 $this->error('unexpected:', $this->getTokenValue($token, true));
    00247
    00248             return self::FINAL_STATE;
    00249         }
    00250     }
    00251 ?>