Rajout de doctrine/orm
[zf2.biz/galerie.git] / vendor / doctrine / dbal / lib / Doctrine / DBAL / Cache / ResultCacheStatement.php
1 <?php
2 /*
3  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14  *
15  * This software consists of voluntary contributions made by many individuals
16  * and is licensed under the MIT license. For more information, see
17  * <http://www.doctrine-project.org>.
18  */
19
20 namespace Doctrine\DBAL\Cache;
21
22 use Doctrine\DBAL\Driver\Statement;
23 use Doctrine\DBAL\Driver\ResultStatement;
24 use Doctrine\DBAL\Connection;
25 use Doctrine\Common\Cache\Cache;
26 use PDO;
27
28 /**
29  * Cache statement for SQL results.
30  *
31  * A result is saved in multiple cache keys, there is the originally specified
32  * cache key which is just pointing to result rows by key. The following things
33  * have to be ensured:
34  *
35  * 1. lifetime of the original key has to be longer than that of all the individual rows keys
36  * 2. if any one row key is missing the query has to be re-executed.
37  *
38  * Also you have to realize that the cache will load the whole result into memory at once to ensure 2.
39  * This means that the memory usage for cached results might increase by using this feature.
40  */
41 class ResultCacheStatement implements \IteratorAggregate, ResultStatement
42 {
43     /**
44      * @var \Doctrine\Common\Cache\Cache
45      */
46     private $resultCache;
47
48     /**
49      *
50      * @var string
51      */
52     private $cacheKey;
53
54     /**
55      * @var string
56      */
57     private $realKey;
58
59     /**
60      * @var int
61      */
62     private $lifetime;
63
64     /**
65      * @var Doctrine\DBAL\Driver\Statement
66      */
67     private $statement;
68
69     /**
70      * Did we reach the end of the statement?
71      *
72      * @var bool
73      */
74     private $emptied = false;
75
76     /**
77      * @var array
78      */
79     private $data;
80
81     /**
82      * @var int
83      */
84     private $defaultFetchMode = PDO::FETCH_BOTH;
85
86     /**
87      * @param Statement $stmt
88      * @param Cache $resultCache
89      * @param string $cacheKey
90      * @param string $realKey
91      * @param int $lifetime
92      */
93     public function __construct(Statement $stmt, Cache $resultCache, $cacheKey, $realKey, $lifetime)
94     {
95         $this->statement = $stmt;
96         $this->resultCache = $resultCache;
97         $this->cacheKey = $cacheKey;
98         $this->realKey = $realKey;
99         $this->lifetime = $lifetime;
100     }
101
102     /**
103      * Closes the cursor, enabling the statement to be executed again.
104      *
105      * @return boolean              Returns TRUE on success or FALSE on failure.
106      */
107     public function closeCursor()
108     {
109         $this->statement->closeCursor();
110         if ($this->emptied && $this->data !== null) {
111             $data = $this->resultCache->fetch($this->cacheKey);
112             if ( ! $data) {
113                 $data = array();
114             }
115             $data[$this->realKey] = $this->data;
116
117             $this->resultCache->save($this->cacheKey, $data, $this->lifetime);
118             unset($this->data);
119         }
120     }
121
122     /**
123      * columnCount
124      * Returns the number of columns in the result set
125      *
126      * @return integer              Returns the number of columns in the result set represented
127      *                              by the PDOStatement object. If there is no result set,
128      *                              this method should return 0.
129      */
130     public function columnCount()
131     {
132         return $this->statement->columnCount();
133     }
134
135     public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
136     {
137         $this->defaultFetchMode = $fetchMode;
138     }
139
140     public function getIterator()
141     {
142         $data = $this->fetchAll();
143         return new \ArrayIterator($data);
144     }
145
146     /**
147      * fetch
148      *
149      * @see Query::HYDRATE_* constants
150      * @param integer $fetchMode            Controls how the next row will be returned to the caller.
151      *                                      This value must be one of the Query::HYDRATE_* constants,
152      *                                      defaulting to Query::HYDRATE_BOTH
153      *
154      * @return mixed
155      */
156     public function fetch($fetchMode = null)
157     {
158         if ($this->data === null) {
159             $this->data = array();
160         }
161
162         $row = $this->statement->fetch(PDO::FETCH_ASSOC);
163         if ($row) {
164             $this->data[] = $row;
165
166             $fetchMode = $fetchMode ?: $this->defaultFetchMode;
167
168             if ($fetchMode == PDO::FETCH_ASSOC) {
169                 return $row;
170             } else if ($fetchMode == PDO::FETCH_NUM) {
171                 return array_values($row);
172             } else if ($fetchMode == PDO::FETCH_BOTH) {
173                 return array_merge($row, array_values($row));
174             } else if ($fetchMode == PDO::FETCH_COLUMN) {
175                 return reset($row);
176             } else {
177                 throw new \InvalidArgumentException("Invalid fetch-style given for caching result.");
178             }
179         }
180         $this->emptied = true;
181         return false;
182     }
183
184     /**
185      * Returns an array containing all of the result set rows
186      *
187      * @param integer $fetchMode            Controls how the next row will be returned to the caller.
188      *                                      This value must be one of the Query::HYDRATE_* constants,
189      *                                      defaulting to Query::HYDRATE_BOTH
190      *
191      * @return array
192      */
193     public function fetchAll($fetchMode = null)
194     {
195         $rows = array();
196         while ($row = $this->fetch($fetchMode)) {
197             $rows[] = $row;
198         }
199         return $rows;
200     }
201
202     /**
203      * fetchColumn
204      * Returns a single column from the next row of a
205      * result set or FALSE if there are no more rows.
206      *
207      * @param integer $columnIndex          0-indexed number of the column you wish to retrieve from the row. If no
208      *                                      value is supplied, PDOStatement->fetchColumn()
209      *                                      fetches the first column.
210      *
211      * @return string                       returns a single column in the next row of a result set.
212      */
213     public function fetchColumn($columnIndex = 0)
214     {
215         $row = $this->fetch(PDO::FETCH_NUM);
216         if (!isset($row[$columnIndex])) {
217             // TODO: verify this is correct behavior
218             return false;
219         }
220         return $row[$columnIndex];
221     }
222
223     /**
224      * rowCount
225      * rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement
226      * executed by the corresponding object.
227      *
228      * If the last SQL statement executed by the associated Statement object was a SELECT statement,
229      * some databases may return the number of rows returned by that statement. However,
230      * this behaviour is not guaranteed for all databases and should not be
231      * relied on for portable applications.
232      *
233      * @return integer                      Returns the number of rows.
234      */
235     public function rowCount()
236     {
237         return $this->statement->rowCount();
238     }
239 }