Skip to content

Commit 34af072

Browse files
committed
- Added Kir\MySQL\Builder\RunnableSelect::fetchRowsLazy(Closure $callback = null) to make use of PHP5.5's yield
1 parent 6230587 commit 34af072

File tree

4 files changed

+137
-68
lines changed

4 files changed

+137
-68
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
namespace Kir\MySQL\Builder\Helpers;
3+
4+
use Kir\MySQL\Builder\QueryStatement;
5+
6+
abstract class FieldTypeProvider {
7+
/**
8+
* @param QueryStatement $statement
9+
* @return array
10+
*/
11+
public static function getFieldTypes(QueryStatement $statement) {
12+
$c = $statement->columnCount();
13+
$fieldTypes = array();
14+
for($i=0; $i<$c+20; $i++) {
15+
$column = $statement->getColumnMeta($i);
16+
$fieldTypes[$column['name']] = self::getTypeFromNativeType($column['native_type']);
17+
}
18+
return $fieldTypes;
19+
}
20+
21+
/**
22+
* @param string $type
23+
* @return string
24+
*/
25+
private static function getTypeFromNativeType($type) {
26+
switch ($type) {
27+
case 'NEWDECIMAL':
28+
case 'DECIMAL':
29+
case 'FLOAT':
30+
case 'DOUBLE':
31+
return 'f';
32+
case 'TINY':
33+
case 'SHORT':
34+
case 'LONG':
35+
case 'LONGLONG':
36+
case 'INT24':
37+
return 'i';
38+
}
39+
return $type;
40+
}
41+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
namespace Kir\MySQL\Builder\Helpers;
3+
4+
class FieldValueConverter {
5+
/**
6+
* @param array $row
7+
* @param array $columnDefinitions
8+
* @return array
9+
*/
10+
public static function convertValues(array $row, array $columnDefinitions) {
11+
foreach($row as $key => &$value) {
12+
if($value !== null) {
13+
$value = self::convertValue($value, $columnDefinitions[$key]);
14+
}
15+
}
16+
return $row;
17+
}
18+
19+
/**
20+
* @param mixed $value
21+
* @param string $type
22+
* @return mixed
23+
*/
24+
private function convertValue($value, $type) {
25+
switch ($type) {
26+
case 'i':
27+
return (int) $value;
28+
case 'f':
29+
return (float) $value;
30+
}
31+
return $value;
32+
}
33+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
namespace Kir\MySQL\Builder\Helpers;
3+
4+
use Closure;
5+
use Generator;
6+
use Kir\MySQL\Builder\QueryStatement;
7+
8+
class LazyRowGenerator {
9+
/** @var bool */
10+
private $preserveTypes;
11+
12+
/**
13+
* @param bool $preserveTypes
14+
*/
15+
public function __construct($preserveTypes) {
16+
$this->preserveTypes = $preserveTypes;
17+
}
18+
19+
/**
20+
* @param QueryStatement $statement
21+
* @param Closure $callback
22+
* @return array[]|Generator
23+
*/
24+
public function generate(QueryStatement $statement, Closure $callback) {
25+
while($row = $statement->fetch(\PDO::FETCH_ASSOC)) {
26+
if($this->preserveTypes) {
27+
$columnDefinitions = FieldTypeProvider::getFieldTypes($statement);
28+
$row = FieldValueConverter::convertValues($row, $columnDefinitions);
29+
}
30+
if($callback !== null) {
31+
$row = call_user_func($callback);
32+
if($row !== null) {
33+
yield $row;
34+
}
35+
} else {
36+
yield $row;
37+
}
38+
}
39+
$statement->closeCursor();
40+
}
41+
}

src/Builder/RunnableSelect.php

Lines changed: 22 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
<?php
22
namespace Kir\MySQL\Builder;
33

4+
use Generator;
5+
use Kir\MySQL\Builder\Helpers\FieldTypeProvider;
6+
use Kir\MySQL\Builder\Helpers\FieldValueConverter;
7+
use Kir\MySQL\Builder\Helpers\LazyRowGenerator;
8+
49
/**
510
*/
611
class RunnableSelect extends Select {
@@ -55,9 +60,9 @@ public function fetchRows(\Closure $callback = null) {
5560
$statement = $this->createStatement();
5661
$data = $statement->fetchAll(\PDO::FETCH_ASSOC);
5762
if($this->preserveTypes) {
58-
$columnDefinitions = $this->getFieldTypes($statement);
63+
$columnDefinitions = FieldTypeProvider::getFieldTypes($statement);
5964
foreach($data as &$row) {
60-
$row = $this->convertValues($row, $columnDefinitions);
65+
$row = FieldValueConverter::convertValues($row, $columnDefinitions);
6166
}
6267
}
6368
if($callback !== null) {
@@ -67,6 +72,19 @@ public function fetchRows(\Closure $callback = null) {
6772
return $data;
6873
}
6974

75+
/**
76+
* @param \Closure $callback
77+
* @return array[]|Generator
78+
*/
79+
public function fetchRowsLazy(\Closure $callback = null) {
80+
if(version_compare(PHP_VERSION, '5.5', '<=')) {
81+
return $this->fetchRows($callback);
82+
}
83+
$statement = $this->createStatement();
84+
$generator = new LazyRowGenerator($this->preserveTypes);
85+
return $generator->generate($statement, $callback);
86+
}
87+
7088
/**
7189
* @return string[]
7290
*/
@@ -78,8 +96,8 @@ public function fetchRow() {
7896
return array();
7997
}
8098
if($this->preserveTypes) {
81-
$columnDefinitions = $this->getFieldTypes($statement);
82-
$row = $this->convertValues($row, $columnDefinitions);
99+
$columnDefinitions = FieldTypeProvider::getFieldTypes($statement);
100+
$row = FieldValueConverter::convertValues($row, $columnDefinitions);
83101
}
84102
$statement->closeCursor();
85103
return $row;
@@ -174,68 +192,4 @@ private function createStatement() {
174192
}
175193
return $statement;
176194
}
177-
178-
/**
179-
* @param QueryStatement $statement
180-
* @return array
181-
*/
182-
private function getFieldTypes($statement) {
183-
$c = $statement->columnCount();
184-
$fieldTypes = array();
185-
for($i=0; $i<$c+20; $i++) {
186-
$column = $statement->getColumnMeta($i);
187-
$fieldTypes[$column['name']] = $this->getTypeFromNativeType($column['native_type']);
188-
}
189-
return $fieldTypes;
190-
}
191-
192-
/**
193-
* @param string $type
194-
* @return string
195-
*/
196-
private function getTypeFromNativeType($type) {
197-
switch ($type) {
198-
case 'NEWDECIMAL':
199-
case 'DECIMAL':
200-
case 'FLOAT':
201-
case 'DOUBLE':
202-
return 'f';
203-
case 'TINY':
204-
case 'SHORT':
205-
case 'LONG':
206-
case 'LONGLONG':
207-
case 'INT24':
208-
return 'i';
209-
}
210-
return $type;
211-
}
212-
213-
/**
214-
* @param array $row
215-
* @param array $columnDefinitions
216-
* @return mixed
217-
*/
218-
private function convertValues(array $row, array $columnDefinitions) {
219-
foreach($row as $key => &$value) {
220-
if($value !== null) {
221-
$value = $this->convertValue($value, $columnDefinitions[$key]);
222-
}
223-
}
224-
return $row;
225-
}
226-
227-
/**
228-
* @param mixed $value
229-
* @param string $type
230-
* @return mixed
231-
*/
232-
private function convertValue($value, $type) {
233-
switch ($type) {
234-
case 'i':
235-
return (int) $value;
236-
case 'f':
237-
return (float) $value;
238-
}
239-
return $value;
240-
}
241195
}

0 commit comments

Comments
 (0)