55use PDO ;
66use PDOStatement ;
77
8+ /**
9+ */
810class RunnableSelect extends Select {
11+ /**
12+ * @var array
13+ */
14+ private $ values = array ();
15+
16+ /**
17+ * @var bool
18+ */
19+ private $ preserveTypes ;
20+
21+ /**
22+ * @param array $values
23+ * @return $this
24+ */
25+ public function bindValues (array $ values ) {
26+ $ this ->values = array_merge ($ this ->values , $ values );
27+ return $ this ;
28+ }
29+
30+ /**
31+ * @param string $key
32+ * @param string|int|bool|float|null $value
33+ * @return $this
34+ */
35+ public function bindValue ($ key , $ value ) {
36+ $ this ->values [$ key ] = $ value ;
37+ return $ this ;
38+ }
39+
40+ /**
41+ * @return $this
42+ */
43+ public function clearValues () {
44+ $ this ->values = array ();
45+ return $ this ;
46+ }
47+
48+ /**
49+ * @param bool $preserveTypes
50+ * @return $this
51+ */
52+ public function setPreserveTypes ($ preserveTypes = true ) {
53+ $ this ->preserveTypes = $ preserveTypes ;
54+ return $ this ;
55+ }
56+
957 /**
1058 * @param Closure $callback
1159 * @return array[]
1260 */
1361 public function fetchRows (Closure $ callback = null ) {
1462 $ statement = $ this ->createStatement ();
63+ $ statement ->execute ($ this ->values );
1564 $ data = $ statement ->fetchAll (PDO ::FETCH_ASSOC );
1665 if ($ callback !== null ) {
1766 $ data = array_map ($ callback , $ data );
1867 }
1968 $ statement ->closeCursor ();
69+
70+ if ($ this ->preserveTypes ) {
71+ $ columnDefinitions = $ this ->getFieldTypes ($ statement );
72+ foreach ($ data as &$ row ) {
73+ $ row = $ this ->convertValues ($ row , $ columnDefinitions );
74+ }
75+ }
76+
2077 return $ data ;
2178 }
2279
@@ -25,10 +82,18 @@ public function fetchRows(Closure $callback = null) {
2582 */
2683 public function fetchRow () {
2784 $ statement = $ this ->createStatement ();
85+ $ statement ->execute ($ this ->values );
2886 $ row = $ statement ->fetch (PDO ::FETCH_ASSOC );
2987 if (!is_array ($ row )) {
3088 return array ();
3189 }
90+ if ($ this ->preserveTypes ) {
91+ $ columnDefinitions = $ this ->getFieldTypes ($ statement );
92+ $ row = $ this ->convertValues ($ row , $ columnDefinitions );
93+ }
94+
95+ $ statement ->closeCursor ();
96+
3297 return $ row ;
3398 }
3499
@@ -48,6 +113,7 @@ public function fetchArray() {
48113 */
49114 public function fetchValue ($ default = null ) {
50115 $ statement = $ this ->createStatement ();
116+ $ statement ->execute ($ this ->values );
51117 $ row = $ statement ->fetch (PDO ::FETCH_ASSOC );
52118 if (!is_array ($ row )) {
53119 return $ default ;
@@ -62,6 +128,68 @@ public function fetchValue($default = null) {
62128 * @return PDOStatement
63129 */
64130 private function createStatement () {
65- return $ this ->db ()->query ($ this ->__toString ());
131+ return $ this ->db ()->prepare ($ this ->__toString ());
132+ }
133+
134+ /**
135+ * @param PDOStatement $statement
136+ * @return array
137+ */
138+ private function getFieldTypes ($ statement ) {
139+ $ c = $ statement ->columnCount ();
140+ $ fieldTypes = array ();
141+ for ($ i =0 ; $ i <$ c +20 ; $ i ++) {
142+ $ column = $ statement ->getColumnMeta ($ i );
143+ $ fieldTypes [$ column ['name ' ]] = $ this ->getTypeFromNativeType ($ column ['native_type ' ]);
144+ }
145+ return $ fieldTypes ;
146+ }
147+
148+ /**
149+ * @param string $type
150+ * @return string
151+ */
152+ private function getTypeFromNativeType ($ type ) {
153+ switch ($ type ) {
154+ case 'NEWDECIMAL ' :
155+ case 'DECIMAL ' :
156+ case 'FLOAT ' :
157+ case 'DOUBLE ' :
158+ return 'f ' ;
159+ case 'TINY ' :
160+ case 'SHORT ' :
161+ case 'LONG ' :
162+ case 'LONGLONG ' :
163+ case 'INT24 ' :
164+ return 'i ' ;
165+ }
166+ return $ type ;
167+ }
168+
169+ /**
170+ * @param array $row
171+ * @param array $columnDefinitions
172+ * @return mixed
173+ */
174+ private function convertValues (array $ row , array $ columnDefinitions ) {
175+ foreach ($ row as $ key => &$ value ) {
176+ $ value = $ this ->convertValue ($ value , $ columnDefinitions [$ key ]);
177+ }
178+ return $ row ;
179+ }
180+
181+ /**
182+ * @param mixed $value
183+ * @param string $type
184+ * @return mixed
185+ */
186+ private function convertValue ($ value , $ type ) {
187+ switch ($ type ) {
188+ case 'i ' :
189+ return (int ) $ value ;
190+ case 'f ' :
191+ return (float ) $ value ;
192+ }
193+ return $ value ;
66194 }
67195}
0 commit comments