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