1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15: namespace Cake\Database\Statement;
16:
17: use Cake\Database\StatementInterface;
18: use Cake\Database\TypeConverterTrait;
19: use Iterator;
20:
21: 22: 23: 24: 25: 26:
27: class BufferedStatement implements Iterator, StatementInterface
28: {
29: use TypeConverterTrait;
30:
31: 32: 33: 34: 35:
36: protected $_allFetched = false;
37:
38: 39: 40: 41: 42:
43: protected $statement;
44:
45: 46: 47: 48: 49:
50: protected $_driver;
51:
52: 53: 54: 55: 56:
57: protected $buffer = [];
58:
59: 60: 61: 62: 63:
64: protected $_hasExecuted = false;
65:
66: 67: 68: 69: 70:
71: protected $index = 0;
72:
73: 74: 75: 76: 77: 78:
79: public function __construct(StatementInterface $statement, $driver)
80: {
81: $this->statement = $statement;
82: $this->_driver = $driver;
83: }
84:
85: 86: 87: 88: 89: 90:
91: public function __get($property)
92: {
93: if ($property === 'queryString') {
94: return $this->statement->queryString;
95: }
96: }
97:
98: 99: 100:
101: public function bindValue($column, $value, $type = 'string')
102: {
103: $this->statement->bindValue($column, $value, $type);
104: }
105:
106: 107: 108:
109: public function closeCursor()
110: {
111: $this->statement->closeCursor();
112: }
113:
114: 115: 116:
117: public function columnCount()
118: {
119: return $this->statement->columnCount();
120: }
121:
122: 123: 124:
125: public function errorCode()
126: {
127: return $this->statement->errorCode();
128: }
129:
130: 131: 132:
133: public function errorInfo()
134: {
135: return $this->statement->errorInfo();
136: }
137:
138: 139: 140:
141: public function execute($params = null)
142: {
143: $this->_reset();
144: $this->_hasExecuted = true;
145:
146: return $this->statement->execute($params);
147: }
148:
149: 150: 151:
152: public function fetchColumn($position)
153: {
154: $result = $this->fetch(static::FETCH_TYPE_NUM);
155: if (isset($result[$position])) {
156: return $result[$position];
157: }
158:
159: return false;
160: }
161:
162: 163: 164: 165: 166: 167:
168: public function count()
169: {
170: return $this->rowCount();
171: }
172:
173: 174: 175:
176: public function bind($params, $types)
177: {
178: $this->statement->bind($params, $types);
179: }
180:
181: 182: 183:
184: public function lastInsertId($table = null, $column = null)
185: {
186: return $this->statement->lastInsertId($table, $column);
187: }
188:
189: 190: 191: 192: 193: 194:
195: public function fetch($type = self::FETCH_TYPE_NUM)
196: {
197: if ($this->_allFetched) {
198: $row = false;
199: if (isset($this->buffer[$this->index])) {
200: $row = $this->buffer[$this->index];
201: }
202: $this->index += 1;
203:
204: if ($row && $type === static::FETCH_TYPE_NUM) {
205: return array_values($row);
206: }
207:
208: return $row;
209: }
210:
211: $record = $this->statement->fetch($type);
212: if ($record === false) {
213: $this->_allFetched = true;
214: $this->statement->closeCursor();
215:
216: return false;
217: }
218: $this->buffer[] = $record;
219:
220: return $record;
221: }
222:
223: 224: 225:
226: public function fetchAssoc()
227: {
228: $result = $this->fetch(static::FETCH_TYPE_ASSOC);
229:
230: return $result ?: [];
231: }
232:
233: 234: 235: 236: 237: 238:
239: public function fetchAll($type = self::FETCH_TYPE_NUM)
240: {
241: if ($this->_allFetched) {
242: return $this->buffer;
243: }
244: $results = $this->statement->fetchAll($type);
245: if ($results !== false) {
246: $this->buffer = array_merge($this->buffer, $results);
247: }
248: $this->_allFetched = true;
249: $this->statement->closeCursor();
250:
251: return $this->buffer;
252: }
253:
254: 255: 256:
257: public function rowCount()
258: {
259: if (!$this->_allFetched) {
260: $this->fetchAll(static::FETCH_TYPE_ASSOC);
261: }
262:
263: return count($this->buffer);
264: }
265:
266: 267: 268: 269: 270:
271: protected function _reset()
272: {
273: $this->buffer = [];
274: $this->_allFetched = false;
275: $this->index = 0;
276: }
277:
278: 279: 280: 281: 282:
283: public function key()
284: {
285: return $this->index;
286: }
287:
288: 289: 290: 291: 292:
293: public function current()
294: {
295: return $this->buffer[$this->index];
296: }
297:
298: 299: 300: 301: 302:
303: public function rewind()
304: {
305: $this->index = 0;
306: }
307:
308: 309: 310: 311: 312:
313: public function valid()
314: {
315: $old = $this->index;
316: $row = $this->fetch(self::FETCH_TYPE_ASSOC);
317:
318:
319:
320: $this->index = $old;
321:
322: return $row !== false;
323: }
324:
325: 326: 327: 328: 329:
330: public function next()
331: {
332: $this->index += 1;
333: }
334:
335: 336: 337: 338: 339:
340: public function getInnerStatement()
341: {
342: return $this->statement;
343: }
344: }
345: