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, 'resource' => PDO::PARAM_LOB, 'NULL' => PDO::PARAM_NULL);
65: foreach ($params as $key => $value) {
66: $type = gettype($value);
67: $this->bindValue(is_int($key) ? $key + 1 : $key, $value, isset($types[$type]) ? $types[$type] : PDO::PARAM_STR);
68: }
69:
70: $time = microtime(TRUE);
71: try {
72: parent::execute();
73: } catch (\PDOException $e) {
74: $e->queryString = $this->queryString;
75: throw $e;
76: }
77: $this->time = microtime(TRUE) - $time;
78: $this->connection->__call('onQuery', array($this, $params)); 79:
80: return $this;
81: }
82:
83:
84:
85: 86: 87: 88:
89: public function fetchPairs()
90: {
91: return $this->fetchAll(PDO::FETCH_KEY_PAIR); 92: }
93:
94:
95:
96: 97: 98: 99: 100:
101: public function normalizeRow($row)
102: {
103: if ($this->types === NULL) {
104: try {
105: $this->types = array();
106: foreach ($row as $key => $foo) {
107: $type = $this->getColumnMeta(count($this->types));
108: if (isset($type['native_type'])) {
109: $this->types[$key] = DatabaseReflection::detectType($type['native_type']);
110: }
111: }
112: } catch (\PDOException $e) {
113: }
114: }
115: foreach ($this->types as $key => $type) {
116: $value = $row[$key];
117: if ($value === NULL || $value === FALSE || $type === DatabaseReflection::FIELD_TEXT) {
118:
119: } elseif ($type === DatabaseReflection::FIELD_INTEGER) {
120: $row[$key] = is_float($tmp = $value * 1) ? $value : $tmp;
121:
122: } elseif ($type === DatabaseReflection::FIELD_FLOAT) {
123: $row[$key] = (string) ($tmp = (float) $value) === $value ? $tmp : $value;
124:
125: } elseif ($type === DatabaseReflection::FIELD_BOOL) {
126: $row[$key] = ((bool) $value) && $value !== 'f' && $value !== 'F';
127: }
128: }
129:
130: return $this->connection->getSupplementalDriver()->normalizeRow($row, $this);
131: }
132:
133:
134:
135:
136:
137:
138:
139: 140: 141: 142:
143: public function dump()
144: {
145: echo "\n<table class=\"dump\">\n<caption>" . htmlSpecialChars($this->queryString) . "</caption>\n";
146: if (!$this->columnCount()) {
147: echo "\t<tr>\n\t\t<th>Affected rows:</th>\n\t\t<td>", $this->rowCount(), "</td>\n\t</tr>\n</table>\n";
148: return;
149: }
150: $i = 0;
151: foreach ($this as $row) {
152: if ($i === 0) {
153: echo "<thead>\n\t<tr>\n\t\t<th>#row</th>\n";
154: foreach ($row as $col => $foo) {
155: echo "\t\t<th>" . htmlSpecialChars($col) . "</th>\n";
156: }
157: echo "\t</tr>\n</thead>\n<tbody>\n";
158: }
159: echo "\t<tr>\n\t\t<th>", $i, "</th>\n";
160: foreach ($row as $col) {
161: 162: echo "\t\t<td>", htmlSpecialChars($col), "</td>\n";
163: }
164: echo "\t</tr>\n";
165: $i++;
166: }
167:
168: if ($i === 0) {
169: echo "\t<tr>\n\t\t<td><em>empty result set</em></td>\n\t</tr>\n</table>\n";
170: } else {
171: echo "</tbody>\n</table>\n";
172: }
173: }
174:
175:
176:
177:
178:
179:
180:
181: 182: 183:
184: public static function getReflection()
185: {
186: return new Nette\Reflection\ClassReflection(get_called_class());
187: }
188:
189:
190:
191: public function __call($name, $args)
192: {
193: return ObjectMixin::call($this, $name, $args);
194: }
195:
196:
197:
198: public function &__get($name)
199: {
200: return ObjectMixin::get($this, $name);
201: }
202:
203:
204:
205: public function __set($name, $value)
206: {
207: return ObjectMixin::set($this, $name, $value);
208: }
209:
210:
211:
212: public function __isset($name)
213: {
214: return ObjectMixin::has($this, $name);
215: }
216:
217:
218:
219: public function __unset($name)
220: {
221: throw new \MemberAccessException("Cannot unset the property {$this->reflection->name}::\$$name.");
222: }
223:
224: }
225: