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: public function dump()
167: {
168: Helpers::dumpResult($this);
169: }
170:
171:
172:
173:
174:
175:
176:
177: 178: 179:
180: public static function getReflection()
181: {
182: return new Nette\Reflection\ClassType(get_called_class());
183: }
184:
185:
186:
187: public function __call($name, $args)
188: {
189: return ObjectMixin::call($this, $name, $args);
190: }
191:
192:
193:
194: public function &__get($name)
195: {
196: return ObjectMixin::get($this, $name);
197: }
198:
199:
200:
201: public function __set($name, $value)
202: {
203: return ObjectMixin::set($this, $name, $value);
204: }
205:
206:
207:
208: public function __isset($name)
209: {
210: return ObjectMixin::has($this, $name);
211: }
212:
213:
214:
215: public function __unset($name)
216: {
217: ObjectMixin::remove($this, $name);
218: }
219:
220: }
221: