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: $value = strpos($value, '.') === FALSE ? $value : rtrim(rtrim($value, '0'), '.');
116: $float = (float) $value;
117: $row[$key] = (string) $float === $value ? $float : $value;
118:
119: } elseif ($type === IReflection::FIELD_BOOL) {
120: $row[$key] = ((bool) $value) && $value !== 'f' && $value !== 'F';
121:
122: } elseif ($type === IReflection::FIELD_DATETIME || $type === IReflection::FIELD_DATE || $type === IReflection::FIELD_TIME) {
123: $row[$key] = new Nette\DateTime($value);
124:
125: }
126: }
127:
128: return $this->connection->getSupplementalDriver()->normalizeRow($row, $this);
129: }
130:
131:
132:
133: private function detectColumnTypes()
134: {
135: if ($this->types === NULL) {
136: $this->types = array();
137: if ($this->connection->getSupplementalDriver()->isSupported(ISupplementalDriver::SUPPORT_COLUMNS_META)) {
138: $col = 0;
139: while ($meta = $this->getColumnMeta($col++)) {
140: if (isset($meta['native_type'])) {
141: $this->types[$meta['name']] = Helpers::detectType($meta['native_type']);
142: }
143: }
144: }
145: }
146: return $this->types;
147: }
148:
149:
150:
151: 152: 153:
154: public function getTime()
155: {
156: return $this->time;
157: }
158:
159:
160:
161:
162:
163:
164:
165: 166: 167: 168:
169: public function dump()
170: {
171: Helpers::dumpResult($this);
172: }
173:
174:
175:
176:
177:
178:
179:
180: 181: 182:
183: public static function getReflection()
184: {
185: return new Nette\Reflection\ClassType(get_called_class());
186: }
187:
188:
189:
190: public function __call($name, $args)
191: {
192: return ObjectMixin::call($this, $name, $args);
193: }
194:
195:
196:
197: public function &__get($name)
198: {
199: return ObjectMixin::get($this, $name);
200: }
201:
202:
203:
204: public function __set($name, $value)
205: {
206: return ObjectMixin::set($this, $name, $value);
207: }
208:
209:
210:
211: public function __isset($name)
212: {
213: return ObjectMixin::has($this, $name);
214: }
215:
216:
217:
218: public function __unset($name)
219: {
220: ObjectMixin::remove($this, $name);
221: }
222:
223: }
224: