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