TimeIntervalsGenerator.class.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************************
00003  *   Copyright (C) 2008 by Ivan Y. Khvostishkov                            *
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 TimeIntervalsGenerator extends QueryIdentification
00016     {
00017         const ITERATOR_ALIAS    = 'iterator';
00018         
00019         private $range      = null;
00020         private $interval   = null;
00021         
00022         private $overlapped = true;
00023         
00024         private $field      = 'time';
00025         
00026         public static function create()
00027         {
00028             return new self;
00029         }
00030         
00031         public function setRange(DateRange $range)
00032         {
00033             $this->range = $range;
00034             
00035             return $this;
00036         }
00037         
00041         public function getRange()
00042         {
00043             return $this->range;
00044         }
00045         
00046         public function setInterval(IntervalUnit $interval)
00047         {
00048             $this->interval = $interval;
00049             
00050             return $this;
00051         }
00052         
00053         public function setOverlapped($overlapped = true)
00054         {
00055             Assert::isBoolean($overlapped);
00056             
00057             $this->overlapped = ($overlapped === true);
00058             
00059             return $this;
00060         }
00061         
00062         public function isOverlapped()
00063         {
00064             return $this->overlapped;
00065         }
00066         
00067         public function getField()
00068         {
00069             return $this->field;
00070         }
00071         
00072         public function setField($field)
00073         {
00074             $this->field = $field;
00075             
00076             return $this;
00077         }
00078         
00082         public function getInterval()
00083         {
00084             return $this->interval;
00085         }
00086         
00087         public function toSelectQuery()
00088         {
00089             if (!$this->range || !$this->interval)
00090                 throw new WrongStateException(
00091                     'define time range and interval units first'
00092                 );
00093             
00094             if (!$this->range->getStart() || !$this->range->getEnd())
00095                 throw new WrongArgumentException(
00096                     'cannot operate with unlimited range'
00097                 );
00098             
00099             $firstIntervalStart =
00100                 $this->interval->truncate(
00101                     $this->range->getStart(), !$this->overlapped
00102                 );
00103                 
00104             $maxIntervals =
00105                 $this->interval->countInRange(
00106                     $this->range, $this->overlapped
00107                 ) - 1;
00108             
00109             $generator = $this->getSeriesGenerator(0, $maxIntervals);
00110             
00111             $result = OSQL::select()->
00112                 from($generator, self::ITERATOR_ALIAS)->
00113                 get(
00114                     Expression::add(
00115                         DBValue::create($firstIntervalStart->toString())->
00116                         castTo(
00117                             DataType::create(DataType::TIMESTAMP)->
00118                             getName()
00119                         ),
00120                         
00121                         Expression::mul(
00122                             DBValue::create("1 {$this->interval->getName()}")->
00123                             castTo(
00124                                 DataType::create(DataType::INTERVAL)->
00125                                 getName()
00126                             ),
00127                             
00128                             DBField::create(self::ITERATOR_ALIAS)
00129                         )
00130                     ),
00131                     $this->field
00132                 );
00133             
00134             return $result;
00135         }
00136         
00137         public function toDialectString(Dialect $dialect)
00138         {
00139             return $this->toSelectQuery()->toDialectString($dialect);
00140         }
00141         
00149         private function getSeriesGenerator($start, $stop, $step = null)
00150         {
00151             if (!$step)
00152                 $result = SQLFunction::create(
00153                     'generate_series',
00154                     DBValue::create($start)->
00155                     castTo(DataType::create(DataType::INTEGER)->getName()),
00156                     
00157                     DBValue::create($stop)->
00158                     castTo(DataType::create(DataType::INTEGER)->getName())
00159                 );
00160             else
00161                 $result = SQLFunction::create(
00162                     'generate_series',
00163                     DBValue::create($start)->
00164                     castTo(DataType::create(DataType::INTEGER)->getName()),
00165                     
00166                     DBValue::create($stop)->
00167                     castTo(DataType::create(DataType::INTEGER)->getName()),
00168                     
00169                     DBValue::create($step)->
00170                     castTo(DataType::create(DataType::INTEGER)->getName())
00171                 );
00172             
00173             return $result;
00174         }
00175     }
00176 ?>