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