1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette\Database;
13:
14: use Nette,
15: PDO,
16: Nette\ObjectMixin;
17:
18:
19:
20: 21: 22: 23: 24:
25: class Statement extends \PDOStatement
26: {
27:
28: private $connection;
29:
30:
31: public $time;
32:
33:
34: private $types;
35:
36:
37:
38: protected function __construct(Connection $connection)
39: {
40: $this->connection = $connection;
41: $this->setFetchMode(PDO::FETCH_CLASS, 'Nette\Database\Row', array($this));
42: }
43:
44:
45:
46: 47: 48:
49: public function getConnection()
50: {
51: return $this->connection;
52: }
53:
54:
55:
56: 57: 58: 59: 60:
61: public function execute($params = array())
62: {
63: static $types = array('boolean' => PDO::PARAM_BOOL, 'integer' => PDO::PARAM_INT,
64: 'resource' => PDO::PARAM_LOB, 'NULL' => PDO::PARAM_NULL);
65:
66: foreach ($params as $key => $value) {
67: $type = gettype($value);
68: $this->bindValue(is_int($key) ? $key + 1 : $key, $value, isset($types[$type]) ? $types[$type] : PDO::PARAM_STR);
69: }
70:
71: $time = microtime(TRUE);
72: try {
73: parent::execute();
74: } catch (\PDOException $e) {
75: $e->queryString = $this->queryString;
76: throw $e;
77: }
78: $this->time = microtime(TRUE) - $time;
79: $this->connection->__call('onQuery', array($this, $params));
80:
81: return $this;
82: }
83:
84:
85:
86: 87: 88: 89:
90: public function fetchPairs()
91: {
92: return $this->fetchAll(PDO::FETCH_KEY_PAIR);
93: }
94:
95:
96:
97: 98: 99: 100: 101:
102: public function normalizeRow($row)
103: {
104: if ($this->types === NULL) {
105: $this->types = array();
106: if ($this->connection->getSupplementalDriver()->supports['meta']) {
107: $col = 0;
108: foreach ($row as $key => $foo) {
109: $type = $this->getColumnMeta($col++);
110: if (isset($type['native_type'])) {
111: $this->types[$key] = Reflection\DatabaseReflection::detectType($type['native_type']);
112: }
113: }
114: }
115: }
116:
117: foreach ($this->types as $key => $type) {
118: $value = $row[$key];
119: if ($value === NULL || $value === FALSE || $type === Reflection\DatabaseReflection::FIELD_TEXT) {
120:
121: } elseif ($type === Reflection\DatabaseReflection::FIELD_INTEGER) {
122: $row[$key] = is_float($tmp = $value * 1) ? $value : $tmp;
123:
124: } elseif ($type === Reflection\DatabaseReflection::FIELD_FLOAT) {
125: $row[$key] = (string) ($tmp = (float) $value) === $value ? $tmp : $value;
126:
127: } elseif ($type === Reflection\DatabaseReflection::FIELD_BOOL) {
128: $row[$key] = ((bool) $value) && $value !== 'f' && $value !== 'F';
129: }
130: }
131:
132: return $this->connection->getSupplementalDriver()->normalizeRow($row, $this);
133: }
134:
135:
136:
137:
138:
139:
140:
141: 142: 143: 144:
145: public function dump()
146: {
147: echo "\n<table class=\"dump\">\n<caption>" . htmlSpecialChars($this->queryString) . "</caption>\n";
148: if (!$this->columnCount()) {
149: echo "\t<tr>\n\t\t<th>Affected rows:</th>\n\t\t<td>", $this->rowCount(), "</td>\n\t</tr>\n</table>\n";
150: return;
151: }
152: $i = 0;
153: foreach ($this as $row) {
154: if ($i === 0) {
155: echo "<thead>\n\t<tr>\n\t\t<th>#row</th>\n";
156: foreach ($row as $col => $foo) {
157: echo "\t\t<th>" . htmlSpecialChars($col) . "</th>\n";
158: }
159: echo "\t</tr>\n</thead>\n<tbody>\n";
160: }
161: echo "\t<tr>\n\t\t<th>", $i, "</th>\n";
162: foreach ($row as $col) {
163:
164: echo "\t\t<td>", htmlSpecialChars($col), "</td>\n";
165: }
166: echo "\t</tr>\n";
167: $i++;
168: }
169:
170: if ($i === 0) {
171: echo "\t<tr>\n\t\t<td><em>empty result set</em></td>\n\t</tr>\n</table>\n";
172: } else {
173: echo "</tbody>\n</table>\n";
174: }
175: }
176:
177:
178:
179:
180:
181:
182:
183: 184: 185:
186: public static function getReflection()
187: {
188: return new Nette\Reflection\ClassType(get_called_class());
189: }
190:
191:
192:
193: public function __call($name, $args)
194: {
195: return ObjectMixin::call($this, $name, $args);
196: }
197:
198:
199:
200: public function &__get($name)
201: {
202: return ObjectMixin::get($this, $name);
203: }
204:
205:
206:
207: public function __set($name, $value)
208: {
209: return ObjectMixin::set($this, $name, $value);
210: }
211:
212:
213:
214: public function __isset($name)
215: {
216: return ObjectMixin::has($this, $name);
217: }
218:
219:
220:
221: public function __unset($name)
222: {
223: ObjectMixin::remove($this, $name);
224: }
225:
226: }
227: