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
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
      • Traits
    • Reflection
    • Security
    • Tokenizer
    • Utils
  • Tracy
    • Bridges
      • Nette
  • none

Classes

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

Interfaces

  • IConventions
  • IRow
  • IRowContainer
  • IStructure
  • ISupplementalDriver

Exceptions

  • ConnectionException
  • ConstraintViolationException
  • DriverException
  • ForeignKeyConstraintViolationException
  • NotNullConstraintViolationException
  • UniqueConstraintViolationException
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  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: class ResultSet implements \Iterator, IRowContainer
 18: {
 19:     use Nette\SmartObject;
 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 = ['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:                 // do nothing
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+)(\.\d+)?\z#', $value, $m);
180:                 $row[$key] = new \DateInterval("PT$m[2]H$m[3]M$m[4]S");
181:                 if (PHP_VERSION_ID >= 70100) {
182:                     $row[$key]->f = isset($m[5]) ? (float) $m[5] : 0.0;
183:                 }
184:                 $row[$key]->invert = (int) (bool) $m[1];
185: 
186:             } elseif ($type === IStructure::FIELD_UNIX_TIMESTAMP) {
187:                 $row[$key] = Nette\Utils\DateTime::from($value);
188:             }
189:         }
190: 
191:         return $this->supplementalDriver->normalizeRow($row);
192:     }
193: 
194: 
195:     /********************* misc tools ****************d*g**/
196: 
197: 
198:     /**
199:      * Displays complete result set as HTML table for debug purposes.
200:      * @return void
201:      */
202:     public function dump()
203:     {
204:         Helpers::dumpResult($this);
205:     }
206: 
207: 
208:     /********************* interface Iterator ****************d*g**/
209: 
210: 
211:     public function rewind()
212:     {
213:         if ($this->result === false) {
214:             throw new Nette\InvalidStateException('Nette\\Database\\ResultSet implements only one way iterator.');
215:         }
216:     }
217: 
218: 
219:     public function current()
220:     {
221:         return $this->result;
222:     }
223: 
224: 
225:     public function key()
226:     {
227:         return $this->resultKey;
228:     }
229: 
230: 
231:     public function next()
232:     {
233:         $this->result = false;
234:     }
235: 
236: 
237:     public function valid()
238:     {
239:         if ($this->result) {
240:             return true;
241:         }
242: 
243:         return $this->fetch() !== false;
244:     }
245: 
246: 
247:     /********************* interface IRowContainer ****************d*g**/
248: 
249: 
250:     /**
251:      * @inheritDoc
252:      */
253:     public function fetch()
254:     {
255:         $data = $this->pdoStatement ? $this->pdoStatement->fetch() : null;
256:         if (!$data) {
257:             $this->pdoStatement->closeCursor();
258:             return false;
259: 
260:         } elseif ($this->result === null && count($data) !== $this->pdoStatement->columnCount()) {
261:             $duplicates = Helpers::findDuplicates($this->pdoStatement);
262:             trigger_error("Found duplicate columns in database result set: $duplicates.", E_USER_NOTICE);
263:         }
264: 
265:         $row = new Row;
266:         foreach ($this->normalizeRow($data) as $key => $value) {
267:             if ($key !== '') {
268:                 $row->$key = $value;
269:             }
270:         }
271: 
272:         $this->resultKey++;
273:         return $this->result = $row;
274:     }
275: 
276: 
277:     /**
278:      * Fetches single field.
279:      * @param  int
280:      * @return mixed|false
281:      */
282:     public function fetchField($column = 0)
283:     {
284:         $row = $this->fetch();
285:         return $row ? $row[$column] : false;
286:     }
287: 
288: 
289:     /**
290:      * @inheritDoc
291:      */
292:     public function fetchPairs($key = null, $value = null)
293:     {
294:         return Helpers::toPairs($this->fetchAll(), $key, $value);
295:     }
296: 
297: 
298:     /**
299:      * @inheritDoc
300:      */
301:     public function fetchAll()
302:     {
303:         if ($this->results === null) {
304:             $this->results = iterator_to_array($this);
305:         }
306:         return $this->results;
307:     }
308: 
309: 
310:     /**
311:      * @inheritDoc
312:      */
313:     public function fetchAssoc($path)
314:     {
315:         return Nette\Utils\Arrays::associate($this->fetchAll(), $path);
316:     }
317: }
318: 
Nette 2.4-20180918 API API documentation generated by ApiGen 2.8.0