Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Reflection
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Utils
  • none
  • Tracy
    • Bridges
      • Nette

Classes

  • Connection
  • Context
  • Helpers
  • ResultSet
  • Row
  • SqlLiteral
  • SqlPreprocessor
  • Structure

Interfaces

  • IConventions
  • IReflection
  • IRow
  • IRowContainer
  • IStructure
  • ISupplementalDriver

Exceptions

  • ConnectionException
  • ConstraintViolationException
  • DriverException
  • ForeignKeyConstraintViolationException
  • NotNullConstraintViolationException
  • UniqueConstraintViolationException
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  • Nette homepage
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\Database;
  9: 
 10: use Nette;
 11: use PDO;
 12: 
 13: 
 14: /**
 15:  * Represents a result set.
 16:  *
 17:  * @property-read Connection $connection
 18:  */
 19: class ResultSet extends Nette\Object implements \Iterator, IRowContainer
 20: {
 21:     /** @var Connection */
 22:     private $connection;
 23: 
 24:     /** @var ISupplementalDriver */
 25:     private $supplementalDriver;
 26: 
 27:     /** @var \PDOStatement|NULL */
 28:     private $pdoStatement;
 29: 
 30:     /** @var IRow */
 31:     private $result;
 32: 
 33:     /** @var int */
 34:     private $resultKey = -1;
 35: 
 36:     /** @var IRow[] */
 37:     private $results;
 38: 
 39:     /** @var float */
 40:     private $time;
 41: 
 42:     /** @var string */
 43:     private $queryString;
 44: 
 45:     /** @var array */
 46:     private $params;
 47: 
 48:     /** @var array */
 49:     private $types;
 50: 
 51: 
 52:     public function __construct(Connection $connection, $queryString, array $params)
 53:     {
 54:         $time = microtime(TRUE);
 55:         $this->connection = $connection;
 56:         $this->supplementalDriver = $connection->getSupplementalDriver();
 57:         $this->queryString = $queryString;
 58:         $this->params = $params;
 59: 
 60:         try {
 61:             if (substr($queryString, 0, 2) === '::') {
 62:                 $connection->getPdo()->{substr($queryString, 2)}();
 63:             } elseif ($queryString !== NULL) {
 64:                 static $types = array('boolean' => PDO::PARAM_BOOL, 'integer' => PDO::PARAM_INT,
 65:                     'resource' => PDO::PARAM_LOB, 'NULL' => PDO::PARAM_NULL);
 66:                 $this->pdoStatement = $connection->getPdo()->prepare($queryString);
 67:                 foreach ($params as $key => $value) {
 68:                     $type = gettype($value);
 69:                     $this->pdoStatement->bindValue(is_int($key) ? $key + 1 : $key, $value, isset($types[$type]) ? $types[$type] : PDO::PARAM_STR);
 70:                 }
 71:                 $this->pdoStatement->setFetchMode(PDO::FETCH_ASSOC);
 72:                 $this->pdoStatement->execute();
 73:             }
 74:         } catch (\PDOException $e) {
 75:             $e = $this->supplementalDriver->convertException($e);
 76:             $e->queryString = $queryString;
 77:             throw $e;
 78:         }
 79:         $this->time = microtime(TRUE) - $time;
 80:     }
 81: 
 82: 
 83:     /**
 84:      * @return Connection
 85:      */
 86:     public function getConnection()
 87:     {
 88:         return $this->connection;
 89:     }
 90: 
 91: 
 92:     /**
 93:      * @internal
 94:      * @return \PDOStatement
 95:      */
 96:     public function getPdoStatement()
 97:     {
 98:         return $this->pdoStatement;
 99:     }
100: 
101: 
102:     /**
103:      * @return string
104:      */
105:     public function getQueryString()
106:     {
107:         return $this->queryString;
108:     }
109: 
110: 
111:     /**
112:      * @return array
113:      */
114:     public function getParameters()
115:     {
116:         return $this->params;
117:     }
118: 
119: 
120:     /**
121:      * @return int
122:      */
123:     public function getColumnCount()
124:     {
125:         return $this->pdoStatement ? $this->pdoStatement->columnCount() : NULL;
126:     }
127: 
128: 
129:     /**
130:      * @return int
131:      */
132:     public function getRowCount()
133:     {
134:         return $this->pdoStatement ? $this->pdoStatement->rowCount() : NULL;
135:     }
136: 
137: 
138:     /**
139:      * @return float
140:      */
141:     public function getTime()
142:     {
143:         return $this->time;
144:     }
145: 
146: 
147:     /**
148:      * Normalizes result row.
149:      * @param  array
150:      * @return array
151:      */
152:     public function normalizeRow($row)
153:     {
154:         if ($this->types === NULL) {
155:             $this->types = (array) $this->supplementalDriver->getColumnTypes($this->pdoStatement);
156:         }
157: 
158:         foreach ($this->types as $key => $type) {
159:             $value = $row[$key];
160:             if ($value === NULL || $value === FALSE || $type === IStructure::FIELD_TEXT) {
161: 
162:             } elseif ($type === IStructure::FIELD_INTEGER) {
163:                 $row[$key] = is_float($tmp = $value * 1) ? $value : $tmp;
164: 
165:             } elseif ($type === IStructure::FIELD_FLOAT) {
166:                 if (($pos = strpos($value, '.')) !== FALSE) {
167:                     $value = rtrim(rtrim($pos === 0 ? "0$value" : $value, '0'), '.');
168:                 }
169:                 $float = (float) $value;
170:                 $row[$key] = (string) $float === $value ? $float : $value;
171: 
172:             } elseif ($type === IStructure::FIELD_BOOL) {
173:                 $row[$key] = ((bool) $value) && $value !== 'f' && $value !== 'F';
174: 
175:             } elseif ($type === IStructure::FIELD_DATETIME || $type === IStructure::FIELD_DATE || $type === IStructure::FIELD_TIME) {
176:                 $row[$key] = new Nette\Utils\DateTime($value);
177: 
178:             } elseif ($type === IStructure::FIELD_TIME_INTERVAL) {
179:                 preg_match('#^(-?)(\d+)\D(\d+)\D(\d+)\z#', $value, $m);
180:                 $row[$key] = new \DateInterval("PT$m[2]H$m[3]M$m[4]S");
181:                 $row[$key]->invert = (int) (bool) $m[1];
182: 
183:             } elseif ($type === IStructure::FIELD_UNIX_TIMESTAMP) {
184:                 $row[$key] = Nette\Utils\DateTime::from($value);
185:             }
186:         }
187: 
188:         return $this->supplementalDriver->normalizeRow($row);
189:     }
190: 
191: 
192:     /********************* misc tools ****************d*g**/
193: 
194: 
195:     /**
196:      * Displays complete result set as HTML table for debug purposes.
197:      * @return void
198:      */
199:     public function dump()
200:     {
201:         Helpers::dumpResult($this);
202:     }
203: 
204: 
205:     /********************* interface Iterator ****************d*g**/
206: 
207: 
208:     public function rewind()
209:     {
210:         if ($this->result === FALSE) {
211:             throw new Nette\InvalidStateException('Nette\\Database\\ResultSet implements only one way iterator.');
212:         }
213:     }
214: 
215: 
216:     public function current()
217:     {
218:         return $this->result;
219:     }
220: 
221: 
222:     public function key()
223:     {
224:         return $this->resultKey;
225:     }
226: 
227: 
228:     public function next()
229:     {
230:         $this->result = FALSE;
231:     }
232: 
233: 
234:     public function valid()
235:     {
236:         if ($this->result) {
237:             return TRUE;
238:         }
239: 
240:         return $this->fetch() !== FALSE;
241:     }
242: 
243: 
244:     /********************* interface IRowContainer ****************d*g**/
245: 
246: 
247:     /**
248:      * @inheritDoc
249:      */
250:     public function fetch()
251:     {
252:         $data = $this->pdoStatement ? $this->pdoStatement->fetch() : NULL;
253:         if (!$data) {
254:             $this->pdoStatement->closeCursor();
255:             return FALSE;
256:         }
257: 
258:         $row = new Row;
259:         foreach ($this->normalizeRow($data) as $key => $value) {
260:             if ($key !== '') {
261:                 $row->$key = $value;
262:             }
263:         }
264: 
265:         if ($this->result === NULL && count($data) !== $this->pdoStatement->columnCount()) {
266:             trigger_error('Found duplicate columns in database result set.', E_USER_NOTICE);
267:         }
268: 
269:         $this->resultKey++;
270:         return $this->result = $row;
271:     }
272: 
273: 
274:     /**
275:      * Fetches single field.
276:      * @param  int
277:      * @return mixed|FALSE
278:      */
279:     public function fetchField($column = 0)
280:     {
281:         $row = $this->fetch();
282:         return $row ? $row[$column] : FALSE;
283:     }
284: 
285: 
286:     /**
287:      * @inheritDoc
288:      */
289:     public function fetchPairs($key = NULL, $value = NULL)
290:     {
291:         return Helpers::toPairs($this->fetchAll(), $key, $value);
292:     }
293: 
294: 
295:     /**
296:      * @inheritDoc
297:      */
298:     public function fetchAll()
299:     {
300:         if ($this->results === NULL) {
301:             $this->results = iterator_to_array($this);
302:         }
303:         return $this->results;
304:     }
305: 
306: 
307:     /**
308:      * @inheritDoc
309:      */
310:     public function fetchAssoc($path)
311:     {
312:         return Nette\Utils\Arrays::associate($this->fetchAll(), $path);
313:     }
314: 
315: }
316: 
Nette 2.3-20161221 API API documentation generated by ApiGen 2.8.0