Packages

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
      • Adapters
      • Extensions
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Diagnostics
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
      • PhpGenerator
  • NetteModule
  • None
  • PHP

Classes

  • NGroupedTableSelection
  • NTableRow
  • NTableSelection
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (http://nette.org)
  5:  *
  6:  * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  7:  *
  8:  * For the full copyright and license information, please view
  9:  * the file license.txt that was distributed with this source code.
 10:  * @package Nette\Database\Table
 11:  */
 12: 
 13: 
 14: 
 15: /**
 16:  * Filtered table representation.
 17:  * Selection is based on the great library NotORM http://www.notorm.com written by Jakub Vrana.
 18:  *
 19:  * @author     Jakub Vrana
 20:  * @author     Jan Skrasek
 21:  *
 22:  * @property-read string $sql
 23:  * @package Nette\Database\Table
 24:  */
 25: class NTableSelection extends NObject implements Iterator, ArrayAccess, Countable
 26: {
 27:     /** @var NConnection */
 28:     protected $connection;
 29: 
 30:     /** @var string table name */
 31:     protected $name;
 32: 
 33:     /** @var string primary key field name */
 34:     protected $primary;
 35: 
 36:     /** @var NTableRow[] data read from database in [primary key => ActiveRow] format */
 37:     protected $rows;
 38: 
 39:     /** @var NTableRow[] modifiable data in [primary key => ActiveRow] format */
 40:     protected $data;
 41: 
 42:     /** @var array of column to select */
 43:     protected $select = array();
 44: 
 45:     /** @var array of where conditions */
 46:     protected $where = array();
 47: 
 48:     /** @var array of where conditions for caching */
 49:     protected $conditions = array();
 50: 
 51:     /** @var array of parameters passed to where conditions */
 52:     protected $parameters = array();
 53: 
 54:     /** @var array or columns to order by */
 55:     protected $order = array();
 56: 
 57:     /** @var int number of rows to fetch */
 58:     protected $limit = NULL;
 59: 
 60:     /** @var int first row to fetch */
 61:     protected $offset = NULL;
 62: 
 63:     /** @var string columns to grouping */
 64:     protected $group = '';
 65: 
 66:     /** @var string grouping condition */
 67:     protected $having = '';
 68: 
 69:     /** @var bool recheck referencing keys */
 70:     protected $checkReferenceNewKeys = FALSE;
 71: 
 72:     /** @var NTableSelection[] */
 73:     protected $referenced = array();
 74: 
 75:     /** @var NGroupedTableSelection[] */
 76:     protected $referencing = array();
 77: 
 78:     /** @var array of touched columns */
 79:     protected $accessed;
 80: 
 81:     /** @var array of earlier touched columns */
 82:     protected $prevAccessed;
 83: 
 84:     /** @var array of primary key values */
 85:     protected $keys = array();
 86: 
 87:     /** @var string */
 88:     protected $delimitedName;
 89: 
 90:     /** @var string */
 91:     protected $delimitedPrimary;
 92: 
 93: 
 94: 
 95:     public function __construct($table, NConnection $connection)
 96:     {
 97:         $this->name = $table;
 98:         $this->connection = $connection;
 99:         $this->primary = $connection->getDatabaseReflection()->getPrimary($table);
100:         $this->delimitedName = $this->tryDelimite($this->name);
101:         $this->delimitedPrimary = $connection->getSupplementalDriver()->delimite($this->primary);
102:     }
103: 
104: 
105: 
106:     /**
107:      * Saves data to cache and empty result.
108:      */
109:     public function __destruct()
110:     {
111:         $cache = $this->connection->getCache();
112:         if ($cache && !$this->select && $this->rows !== NULL) {
113:             $cache->save(array(__CLASS__, $this->name, $this->conditions), $this->accessed);
114:         }
115:         $this->rows = NULL;
116:     }
117: 
118: 
119: 
120:     /**
121:      * @return NConnection
122:      */
123:     public function getConnection()
124:     {
125:         return $this->connection;
126:     }
127: 
128: 
129: 
130:     /**
131:      * @return string
132:      */
133:     public function getName()
134:     {
135:         return $this->name;
136:     }
137: 
138: 
139: 
140:     /**
141:      * @return string
142:      */
143:     public function getPrimary()
144:     {
145:         return $this->primary;
146:     }
147: 
148: 
149: 
150:     /**
151:      * Returns row specified by primary key.
152:      * @param  mixed
153:      * @return NTableRow or FALSE if there is no such row
154:      */
155:     public function get($key)
156:     {
157:         // can also use array_pop($this->where) instead of clone to save memory
158:         $clone = clone $this;
159:         $clone->where($this->delimitedPrimary, $key);
160:         return $clone->fetch();
161:     }
162: 
163: 
164: 
165:     /**
166:      * Adds select clause, more calls appends to the end.
167:      * @param  string for example "column, MD5(column) AS column_md5"
168:      * @return NTableSelection provides a fluent interface
169:      */
170:     public function select($columns)
171:     {
172:         $this->__destruct();
173:         $this->select[] = $columns;
174:         return $this;
175:     }
176: 
177: 
178: 
179:     /**
180:      * Selects by primary key.
181:      * @param  mixed
182:      * @return NTableSelection provides a fluent interface
183:      */
184:     public function find($key)
185:     {
186:         return $this->where($this->delimitedPrimary, $key);
187:     }
188: 
189: 
190: 
191:     /**
192:      * Adds where condition, more calls appends with AND.
193:      * @param  string condition possibly containing ?
194:      * @param  mixed
195:      * @param  mixed ...
196:      * @return NTableSelection provides a fluent interface
197:      */
198:     public function where($condition, $parameters = array())
199:     {
200:         if (is_array($condition)) { // where(array('column1' => 1, 'column2 > ?' => 2))
201:             foreach ($condition as $key => $val) {
202:                 if (is_int($key)) {
203:                     $this->where($val); // where('full condition')
204:                 } else {
205:                     $this->where($key, $val);   // where('column', 1)
206:                 }
207:             }
208:             return $this;
209:         }
210: 
211:         $hash = md5(json_encode(func_get_args()));
212:         if (isset($this->conditions[$hash])) {
213:             return $this;
214:         }
215: 
216:         $this->__destruct();
217: 
218:         $this->conditions[$hash] = $condition;
219:         $condition = $this->removeExtraTables($condition);
220:         $condition = $this->tryDelimite($condition);
221: 
222:         $args = func_num_args();
223:         if ($args !== 2 || strpbrk($condition, '?:')) { // where('column < ? OR column > ?', array(1, 2))
224:             if ($args !== 2 || !is_array($parameters)) { // where('column < ? OR column > ?', 1, 2)
225:                 $parameters = func_get_args();
226:                 array_shift($parameters);
227:             }
228:             $this->parameters = array_merge($this->parameters, $parameters);
229: 
230:         } elseif ($parameters === NULL) { // where('column', NULL)
231:             $condition .= ' IS NULL';
232: 
233:         } elseif ($parameters instanceof NTableSelection) { // where('column', $db->$table())
234:             $clone = clone $parameters;
235:             if (!$clone->select) {
236:                 $clone->select = array($clone->primary);
237:             }
238:             if ($this->connection->getAttribute(PDO::ATTR_DRIVER_NAME) !== 'mysql') {
239:                 $condition .= ' IN (' . $clone->getSql() . ')';
240:             } else {
241:                 $in = array();
242:                 foreach ($clone as $row) {
243:                     $this->parameters[] = array_values(iterator_to_array($row));
244:                     $in[] = (count($row) === 1 ? '?' : '(?)');
245:                 }
246:                 $condition .= ' IN (' . ($in ? implode(', ', $in) : 'NULL') . ')';
247:             }
248: 
249:         } elseif (!is_array($parameters)) { // where('column', 'x')
250:             $condition .= ' = ?';
251:             $this->parameters[] = $parameters;
252: 
253:         } else { // where('column', array(1, 2))
254:             if ($parameters) {
255:                 $condition .= " IN (?)";
256:                 $this->parameters[] = $parameters;
257:             } else {
258:                 $condition .= " IN (NULL)";
259:             }
260:         }
261: 
262:         $this->where[] = $condition;
263:         return $this;
264:     }
265: 
266: 
267: 
268:     /**
269:      * Adds order clause, more calls appends to the end.
270:      * @param  string for example 'column1, column2 DESC'
271:      * @return NTableSelection provides a fluent interface
272:      */
273:     public function order($columns)
274:     {
275:         $this->rows = NULL;
276:         $this->order[] = $columns;
277:         return $this;
278:     }
279: 
280: 
281: 
282:     /**
283:      * Sets limit clause, more calls rewrite old values.
284:      * @param  int
285:      * @param  int
286:      * @return NTableSelection provides a fluent interface
287:      */
288:     public function limit($limit, $offset = NULL)
289:     {
290:         $this->rows = NULL;
291:         $this->limit = $limit;
292:         $this->offset = $offset;
293:         return $this;
294:     }
295: 
296: 
297: 
298:     /**
299:      * Sets offset using page number, more calls rewrite old values.
300:      * @param  int
301:      * @param  int
302:      * @return NTableSelection provides a fluent interface
303:      */
304:     public function page($page, $itemsPerPage)
305:     {
306:         $this->rows = NULL;
307:         $this->limit = $itemsPerPage;
308:         $this->offset = ($page - 1) * $itemsPerPage;
309:         return $this;
310:     }
311: 
312: 
313: 
314:     /**
315:      * Sets group clause, more calls rewrite old values.
316:      * @param  string
317:      * @param  string
318:      * @return NTableSelection provides a fluent interface
319:      */
320:     public function group($columns, $having = '')
321:     {
322:         $this->__destruct();
323:         $this->group = $columns;
324:         $this->having = $having;
325:         return $this;
326:     }
327: 
328: 
329: 
330:     /**
331:      * Executes aggregation function.
332:      * @param  string
333:      * @return string
334:      */
335:     public function aggregation($function)
336:     {
337:         $selection = new NTableSelection($this->name, $this->connection);
338:         $selection->where = $this->where;
339:         $selection->parameters = $this->parameters;
340:         $selection->conditions = $this->conditions;
341: 
342:         $selection->select($function);
343: 
344:         foreach ($selection->fetch() as $val) {
345:             return $val;
346:         }
347:     }
348: 
349: 
350: 
351:     /**
352:      * Counts number of rows.
353:      * @param  string
354:      * @return int
355:      */
356:     public function count($column = '')
357:     {
358:         if (!$column) {
359:             $this->execute();
360:             return count($this->data);
361:         }
362:         return $this->aggregation("COUNT($column)");
363:     }
364: 
365: 
366: 
367:     /**
368:      * Returns minimum value from a column.
369:      * @param  string
370:      * @return int
371:      */
372:     public function min($column)
373:     {
374:         return $this->aggregation("MIN($column)");
375:     }
376: 
377: 
378: 
379:     /**
380:      * Returns maximum value from a column.
381:      * @param  string
382:      * @return int
383:      */
384:     public function max($column)
385:     {
386:         return $this->aggregation("MAX($column)");
387:     }
388: 
389: 
390: 
391:     /**
392:      * Returns sum of values in a column.
393:      * @param  string
394:      * @return int
395:      */
396:     public function sum($column)
397:     {
398:         return $this->aggregation("SUM($column)");
399:     }
400: 
401: 
402: 
403:     /**
404:      * Returns SQL query.
405:      * @return string
406:      */
407:     public function getSql()
408:     {
409:         $join = $this->createJoins(implode(',', $this->conditions), TRUE)
410:             + $this->createJoins(implode(',', $this->select) . ",$this->group,$this->having," . implode(',', $this->order));
411: 
412:         $cache = $this->connection->getCache();
413:         if ($this->rows === NULL && $cache && !is_string($this->prevAccessed)) {
414:             $this->accessed = $this->prevAccessed = $cache->load(array(__CLASS__, $this->name, $this->conditions));
415:         }
416: 
417:         $prefix = $join ? "$this->delimitedName." : '';
418:         if ($this->select) {
419:             $cols = $this->tryDelimite($this->removeExtraTables(implode(', ', $this->select)));
420: 
421:         } elseif ($this->prevAccessed) {
422:             $cols = array_map(array($this->connection->getSupplementalDriver(), 'delimite'), array_keys(array_filter($this->prevAccessed)));
423:             $cols = $prefix . implode(', ' . $prefix, $cols);
424: 
425:         } else {
426:             $cols = $prefix . '*';
427:         }
428: 
429:         return "SELECT{$this->topString()} $cols FROM $this->delimitedName" . implode($join) . $this->whereString();
430:     }
431: 
432: 
433: 
434:     protected function createJoins($val, $inner = FALSE)
435:     {
436:         $driver = $this->connection->getSupplementalDriver();
437:         $reflection = $this->connection->getDatabaseReflection();
438:         $joins = array();
439:         preg_match_all('~\\b([a-z][\\w.:]*[.:])([a-z]\\w*|\*)(\\s+IS\\b|\\s*<=>)?~i', $val, $matches);
440:         foreach ($matches[1] as $names) {
441:             $parent = $this->name;
442:             if ($names !== "$parent.") { // case-sensitive
443:                 preg_match_all('~\\b([a-z][\\w]*|\*)([.:])~i', $names, $matches, PREG_SET_ORDER);
444:                 foreach ($matches as $match) {
445:                     list(, $name, $delimiter) = $match;
446: 
447:                     if ($delimiter === ':') {
448:                         list($table, $primary) = $reflection->getHasManyReference($parent, $name);
449:                         $column = $reflection->getPrimary($parent);
450:                     } else {
451:                         list($table, $column) = $reflection->getBelongsToReference($parent, $name);
452:                         $primary = $reflection->getPrimary($table);
453:                     }
454: 
455:                     $joins[$name] = ' '
456:                         . (!isset($joins[$name]) && $inner && !isset($match[3]) ? 'INNER' : 'LEFT')
457:                         . ' JOIN ' . $driver->delimite($table) . ($table !== $name ? ' AS ' . $driver->delimite($name) : '')
458:                         . ' ON ' . $driver->delimite($parent) . '.' . $driver->delimite($column)
459:                         . ' = ' . $driver->delimite($name) . '.' . $driver->delimite($primary);
460: 
461:                     $parent = $name;
462:                 }
463:             }
464:         }
465:         return $joins;
466:     }
467: 
468: 
469: 
470:     /**
471:      * Executes built query.
472:      * @return NULL
473:      */
474:     protected function execute()
475:     {
476:         if ($this->rows !== NULL) {
477:             return;
478:         }
479: 
480:         try {
481:             $result = $this->query($this->getSql());
482: 
483:         } catch (PDOException $exception) {
484:             if (!$this->select && $this->prevAccessed) {
485:                 $this->prevAccessed = '';
486:                 $this->accessed = array();
487:                 $result = $this->query($this->getSql());
488:             } else {
489:                 throw $exception;
490:             }
491:         }
492: 
493:         $this->rows = array();
494:         $result->setFetchMode(PDO::FETCH_ASSOC);
495:         foreach ($result as $key => $row) {
496:             $row = $result->normalizeRow($row);
497:             $this->rows[isset($row[$this->primary]) ? $row[$this->primary] : $key] = $this->createRow($row);
498:         }
499:         $this->data = $this->rows;
500: 
501:         if (isset($row[$this->primary]) && !is_string($this->accessed)) {
502:             $this->accessed[$this->primary] = TRUE;
503:         }
504:     }
505: 
506: 
507: 
508:     protected function createRow(array $row)
509:     {
510:         return new NTableRow($row, $this);
511:     }
512: 
513: 
514: 
515:     protected function whereString()
516:     {
517:         $return = '';
518:         $driver = $this->connection->getAttribute(PDO::ATTR_DRIVER_NAME);
519:         $where = $this->where;
520:         if ($this->limit !== NULL && $driver === 'oci') {
521:             $where[] = ($this->offset ? "rownum > $this->offset AND " : '') . 'rownum <= ' . ($this->limit + $this->offset);
522:         }
523:         if ($where) {
524:             $return .= ' WHERE (' . implode(') AND (', $where) . ')';
525:         }
526:         if ($this->group) {
527:             $return .= ' GROUP BY '. $this->tryDelimite($this->removeExtraTables($this->group));
528:         }
529:         if ($this->having) {
530:             $return .= ' HAVING '. $this->tryDelimite($this->removeExtraTables($this->having));
531:         }
532:         if ($this->order) {
533:             $return .= ' ORDER BY ' . $this->tryDelimite($this->removeExtraTables(implode(', ', $this->order)));
534:         }
535:         if ($this->limit !== NULL && $driver !== 'oci' && $driver !== 'dblib') {
536:             $return .= " LIMIT $this->limit";
537:             if ($this->offset !== NULL) {
538:                 $return .= " OFFSET $this->offset";
539:             }
540:         }
541:         return $return;
542:     }
543: 
544: 
545: 
546:     protected function topString()
547:     {
548:         if ($this->limit !== NULL && $this->connection->getAttribute(PDO::ATTR_DRIVER_NAME) === 'dblib') {
549:             return " TOP ($this->limit)"; //! offset is not supported
550:         }
551:         return '';
552:     }
553: 
554: 
555: 
556:     protected function tryDelimite($s)
557:     {
558:         $driver = $this->connection->getSupplementalDriver();
559:         return preg_replace_callback('#(?<=[^\w`"\[]|^)[a-z_][a-z0-9_]*(?=[^\w`"(\]]|$)#i', create_function('$m', 'extract(NCFix::$vars['.NCFix::uses(array('driver'=>$driver)).'], EXTR_REFS);
560:             return strtoupper($m[0]) === $m[0] ? $m[0] : $driver->delimite($m[0]);
561:         '), $s);
562:     }
563: 
564: 
565: 
566:     protected function removeExtraTables($expression)
567:     {
568:         return preg_replace('~(?:\\b[a-z_][a-z0-9_.:]*[.:])?([a-z_][a-z0-9_]*)[.:]([a-z_*])~i', '\\1.\\2', $expression); // rewrite tab1.tab2.col
569:     }
570: 
571: 
572: 
573:     protected function query($query)
574:     {
575:         return $this->connection->queryArgs($query, $this->parameters);
576:     }
577: 
578: 
579: 
580:     /**
581:      * @internal
582:      * @param  string        column name
583:      * @param  bool|NULL     TRUE - cache, FALSE - don't cache, NULL - remove
584:      * @return bool
585:      */
586:     public function access($key, $cache = TRUE)
587:     {
588:         if ($cache === NULL) {
589:             if (is_array($this->accessed)) {
590:                 $this->accessed[$key] = FALSE;
591:             }
592:             return FALSE;
593:         }
594: 
595:         if ($key === NULL) {
596:             $this->accessed = '';
597: 
598:         } elseif (!is_string($this->accessed)) {
599:             $this->accessed[$key] = $cache;
600:         }
601: 
602:         if ($cache && !$this->select && $this->prevAccessed && ($key === NULL || !isset($this->prevAccessed[$key]))) {
603:             $this->prevAccessed = '';
604:             $this->__destruct();
605:             return TRUE;
606:         }
607:         return FALSE;
608:     }
609: 
610: 
611: 
612:     /********************* manipulation ****************d*g**/
613: 
614: 
615: 
616:     /**
617:      * Inserts row in a table.
618:      * @param  mixed array($column => $value)|Traversable for single row insert or Selection|string for INSERT ... SELECT
619:      * @return NTableRow or FALSE in case of an error or number of affected rows for INSERT ... SELECT
620:      */
621:     public function insert($data)
622:     {
623:         if ($data instanceof NTableSelection) {
624:             $data = $data->getSql();
625: 
626:         } elseif ($data instanceof Traversable) {
627:             $data = iterator_to_array($data);
628:         }
629: 
630:         $return = $this->connection->query("INSERT INTO $this->delimitedName", $data);
631: 
632:         if (!is_array($data)) {
633:             return $return->rowCount();
634:         }
635: 
636:         $this->checkReferenceNewKeys = TRUE;
637: 
638:         if (!isset($data[$this->primary]) && ($id = $this->connection->lastInsertId())) {
639:             $data[$this->primary] = $id;
640:             return $this->rows[$id] = new NTableRow($data, $this);
641: 
642:         } else {
643:             return new NTableRow($data, $this);
644: 
645:         }
646:     }
647: 
648: 
649: 
650:     /**
651:      * Updates all rows in result set.
652:      * @param  array|Traversable ($column => $value)
653:      * @return int number of affected rows or FALSE in case of an error
654:      */
655:     public function update($data)
656:     {
657:         if ($data instanceof Traversable) {
658:             $data = iterator_to_array($data);
659: 
660:         } elseif (!is_array($data)) {
661:             throw new InvalidArgumentException;
662:         }
663: 
664:         if (!$data) {
665:             return 0;
666:         }
667:         // joins in UPDATE are supported only in MySQL
668:         return $this->connection->queryArgs(
669:             'UPDATE' . $this->topString() . " $this->delimitedName SET ?" . $this->whereString(),
670:             array_merge(array($data), $this->parameters)
671:         )->rowCount();
672:     }
673: 
674: 
675: 
676:     /**
677:      * Deletes all rows in result set.
678:      * @return int number of affected rows or FALSE in case of an error
679:      */
680:     public function delete()
681:     {
682:         return $this->query(
683:             'DELETE' . $this->topString() . " FROM $this->delimitedName" . $this->whereString()
684:         )->rowCount();
685:     }
686: 
687: 
688: 
689:     /********************* references ****************d*g**/
690: 
691: 
692: 
693:     /**
694:      * Returns referenced row.
695:      * @param  string
696:      * @param  string
697:      * @param  bool  checks if rows contains the same primary value relations
698:      * @return NTableSelection or array() if the row does not exist
699:      */
700:     public function getReferencedTable($table, $column, $checkReferenceNewKeys = FALSE)
701:     {
702:         $referenced = & $this->referenced["$table.$column"];
703:         if ($referenced === NULL || $checkReferenceNewKeys || $this->checkReferenceNewKeys) {
704:             $keys = array();
705:             foreach ($this->rows as $row) {
706:                 if ($row[$column] === NULL)
707:                     continue;
708: 
709:                 $key = $row[$column] instanceof NTableRow ? $row[$column]->getPrimary() : $row[$column];
710:                 $keys[$key] = TRUE;
711:             }
712: 
713:             if ($referenced !== NULL && $keys === array_keys($this->rows)) {
714:                 $this->checkReferenceNewKeys = FALSE;
715:                 return $referenced;
716:             }
717: 
718:             if ($keys) {
719:                 $referenced = new NTableSelection($table, $this->connection);
720:                 $referenced->where($table . '.' . $referenced->primary, array_keys($keys));
721:             } else {
722:                 $referenced = array();
723:             }
724:         }
725: 
726:         return $referenced;
727:     }
728: 
729: 
730: 
731:     /**
732:      * Returns referencing rows.
733:      * @param  string
734:      * @param  string
735:      * @param  int  primary key
736:      * @param  bool force new instance
737:      * @return NGroupedTableSelection
738:      */
739:     public function getReferencingTable($table, $column, $active = NULL, $forceNewInstance = FALSE)
740:     {
741:         $referencing = & $this->referencing["$table:$column"];
742:         if (!$referencing || $forceNewInstance) {
743:             $referencing = new NGroupedTableSelection($table, $this, $column);
744:             $referencing->where("$table.$column", array_keys((array) $this->rows)); // (array) - is NULL after insert
745:         }
746: 
747:         return $referencing->setActive($active);
748:     }
749: 
750: 
751: 
752:     /********************* interface Iterator ****************d*g**/
753: 
754: 
755: 
756:     public function rewind()
757:     {
758:         $this->execute();
759:         $this->keys = array_keys($this->data);
760:         reset($this->keys);
761:     }
762: 
763: 
764: 
765:     /** @return NTableRow */
766:     public function current()
767:     {
768:         return $this->data[current($this->keys)];
769:     }
770: 
771: 
772: 
773:     /**
774:      * @return string row ID
775:      */
776:     public function key()
777:     {
778:         return current($this->keys);
779:     }
780: 
781: 
782: 
783:     public function next()
784:     {
785:         next($this->keys);
786:     }
787: 
788: 
789: 
790:     public function valid()
791:     {
792:         return current($this->keys) !== FALSE;
793:     }
794: 
795: 
796: 
797:     /********************* interface ArrayAccess ****************d*g**/
798: 
799: 
800: 
801:     /**
802:      * Mimic row.
803:      * @param  string row ID
804:      * @param  NTableRow
805:      * @return NULL
806:      */
807:     public function offsetSet($key, $value)
808:     {
809:         $this->execute();
810:         $this->data[$key] = $value;
811:     }
812: 
813: 
814: 
815:     /**
816:      * Returns specified row.
817:      * @param  string row ID
818:      * @return NTableRow or NULL if there is no such row
819:      */
820:     public function offsetGet($key)
821:     {
822:         $this->execute();
823:         return $this->data[$key];
824:     }
825: 
826: 
827: 
828:     /**
829:      * Tests if row exists.
830:      * @param  string row ID
831:      * @return bool
832:      */
833:     public function offsetExists($key)
834:     {
835:         $this->execute();
836:         return isset($this->data[$key]);
837:     }
838: 
839: 
840: 
841:     /**
842:      * Removes row from result set.
843:      * @param  string row ID
844:      * @return NULL
845:      */
846:     public function offsetUnset($key)
847:     {
848:         $this->execute();
849:         unset($this->data[$key]);
850:     }
851: 
852: 
853: 
854:     /**
855:      * Returns next row of result.
856:      * @return NTableRow or FALSE if there is no row
857:      */
858:     public function fetch()
859:     {
860:         $this->execute();
861:         $return = current($this->data);
862:         next($this->data);
863:         return $return;
864:     }
865: 
866: 
867: 
868:     /**
869:      * Returns all rows as associative array.
870:      * @param  string
871:      * @param  string column name used for an array value or an empty string for the whole row
872:      * @return array
873:      */
874:     public function fetchPairs($key, $value = '')
875:     {
876:         $return = array();
877:         // no $clone->select = array($key, $value) to allow efficient caching with repetitive calls with different parameters
878:         foreach ($this as $row) {
879:             $return[is_object($row[$key]) ? (string) $row[$key] : $row[$key]] = ($value !== '' ? $row[$value] : $row);
880:         }
881:         return $return;
882:     }
883: 
884: }
885: 
Nette Framework 2.0.3 (for PHP 5.2, prefixed) API API documentation generated by ApiGen 2.7.0