@@ -26,6 +26,9 @@ class ResultSet implements \Iterator, IRowContainer
2626 /** @var \PDOStatement|null */
2727 private $ pdoStatement ;
2828
29+ /** @var callable(array, ResultSet): array */
30+ private $ normalizer ;
31+
2932 /** @var Row|false */
3033 private $ result ;
3134
@@ -48,12 +51,13 @@ class ResultSet implements \Iterator, IRowContainer
4851 private $ types ;
4952
5053
51- public function __construct (Connection $ connection , string $ queryString , array $ params )
54+ public function __construct (Connection $ connection , string $ queryString , array $ params, callable $ normalizer = null )
5255 {
5356 $ time = microtime (true );
5457 $ this ->connection = $ connection ;
5558 $ this ->queryString = $ queryString ;
5659 $ this ->params = $ params ;
60+ $ this ->normalizer = $ normalizer ;
5761
5862 try {
5963 if (substr ($ queryString , 0 , 2 ) === ':: ' ) {
@@ -118,57 +122,27 @@ public function getRowCount(): ?int
118122 }
119123
120124
125+ public function getColumnTypes (): array
126+ {
127+ if ($ this ->types === null ) {
128+ $ this ->types = $ this ->connection ->getDriver ()->getColumnTypes ($ this ->pdoStatement );
129+ }
130+ return $ this ->types ;
131+ }
132+
133+
121134 public function getTime (): float
122135 {
123136 return $ this ->time ;
124137 }
125138
126139
127- /**
128- * Normalizes result row.
129- */
140+ /** @internal */
130141 public function normalizeRow (array $ row ): array
131142 {
132- if ($ this ->types === null ) {
133- $ this ->types = $ this ->connection ->getDriver ()->getColumnTypes ($ this ->pdoStatement );
134- }
135-
136- foreach ($ this ->types as $ key => $ type ) {
137- $ value = $ row [$ key ];
138- if ($ value === null || $ value === false || $ type === IStructure::FIELD_TEXT ) {
139- // do nothing
140- } elseif ($ type === IStructure::FIELD_INTEGER ) {
141- $ row [$ key ] = is_float ($ tmp = $ value * 1 ) ? $ value : $ tmp ;
142-
143- } elseif ($ type === IStructure::FIELD_FLOAT ) {
144- if (is_string ($ value ) && ($ pos = strpos ($ value , '. ' )) !== false ) {
145- $ value = rtrim (rtrim ($ pos === 0 ? "0 $ value " : $ value , '0 ' ), '. ' );
146- }
147- $ float = (float ) $ value ;
148- $ row [$ key ] = (string ) $ float === $ value ? $ float : $ value ;
149-
150- } elseif ($ type === IStructure::FIELD_BOOL ) {
151- $ row [$ key ] = ((bool ) $ value ) && $ value !== 'f ' && $ value !== 'F ' ;
152-
153- } elseif (
154- $ type === IStructure::FIELD_DATETIME
155- || $ type === IStructure::FIELD_DATE
156- || $ type === IStructure::FIELD_TIME
157- ) {
158- $ row [$ key ] = new Nette \Utils \DateTime ($ value );
159-
160- } elseif ($ type === IStructure::FIELD_TIME_INTERVAL ) {
161- preg_match ('#^(-?)(\d+)\D(\d+)\D(\d+)(\.\d+)?$#D ' , $ value , $ m );
162- $ row [$ key ] = new \DateInterval ("PT $ m [2 ]H $ m [3 ]M $ m [4 ]S " );
163- $ row [$ key ]->f = isset ($ m [5 ]) ? (float ) $ m [5 ] : 0.0 ;
164- $ row [$ key ]->invert = (int ) (bool ) $ m [1 ];
165-
166- } elseif ($ type === IStructure::FIELD_UNIX_TIMESTAMP ) {
167- $ row [$ key ] = Nette \Utils \DateTime::from ($ value );
168- }
169- }
170-
171- return $ row ;
143+ return $ this ->normalizer
144+ ? ($ this ->normalizer )($ row , $ this )
145+ : $ row ;
172146 }
173147
174148
0 commit comments