1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette\Database;
13:
14: use Nette,
15: Nette\ObjectMixin,
16: Nette\Database\Reflection\DatabaseReflection,
17: PDO;
18:
19:
20:
21: 22: 23: 24: 25:
26: class Statement extends \PDOStatement
27: {
28:
29: private $connection;
30:
31:
32: public $time;
33:
34:
35: private $types;
36:
37:
38:
39: protected function __construct(Connection $connection)
40: {
41: $this->connection = $connection;
42: $this->setFetchMode(PDO::FETCH_CLASS, 'Nette\Database\Row', array($this));
43: }
44:
45:
46:
47: 48: 49:
50: public function getConnection()
51: {
52: return $this->connection;
53: }
54:
55:
56:
57: 58: 59: 60: 61:
62: public function execute($params = array())
63: {
64: static $types = array('boolean' => PDO::PARAM_BOOL, 'integer' => PDO::PARAM_INT,
65: 'resource' => PDO::PARAM_LOB, 'NULL' => PDO::PARAM_NULL);
66:
67: foreach ($params as $key => $value) {
68: $type = gettype($value);
69: $this->bindValue(is_int($key) ? $key + 1 : $key, $value, isset($types[$type]) ? $types[$type] : PDO::PARAM_STR);
70: }
71:
72: $time = microtime(TRUE);
73: try {
74: parent::execute();
75: } catch (\PDOException $e) {
76: $e->queryString = $this->queryString;
77: throw $e;
78: }
79: $this->time = microtime(TRUE) - $time;
80: $this->connection->__call('onQuery', array($this, $params)); 81:
82: return $this;
83: }
84:
85:
86:
87: 88: 89: 90:
91: public function fetchPairs()
92: {
93: return $this->fetchAll(PDO::FETCH_KEY_PAIR); 94: }
95:
96:
97:
98: 99: 100: 101: 102:
103: public function normalizeRow($row)
104: {
105: if ($this->types === NULL) {
106: try {
107: $this->types = array();
108: foreach ($row as $key => $foo) {
109: $type = $this->getColumnMeta(count($this->types));
110: if (isset($type['native_type'])) {
111: $this->types[$key] = DatabaseReflection::detectType($type['native_type']);
112: }
113: }
114: } catch (\PDOException $e) {
115: }
116: }
117: foreach ($this->types as $key => $type) {
118: $value = $row[$key];
119: if ($value === NULL || $value === FALSE || $type === DatabaseReflection::FIELD_TEXT) {
120:
121: } elseif ($type === DatabaseReflection::FIELD_INTEGER) {
122: $row[$key] = is_float($tmp = $value * 1) ? $value : $tmp;
123:
124: } elseif ($type === DatabaseReflection::FIELD_FLOAT) {
125: $row[$key] = (string) ($tmp = (float) $value) === $value ? $tmp : $value;
126:
127: } elseif ($type === 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\ClassReflection(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: