1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette\Database;
13:
14: use Nette,
15: Nette\ObjectMixin,
16: PDO;
17:
18:
19:
20: 21: 22: 23: 24:
25: class Connection extends PDO
26: {
27:
28: private $driver;
29:
30:
31: private $preprocessor;
32:
33:
34: public $databaseReflection;
35:
36:
37: public $cache;
38:
39:
40: public $substitutions = array();
41:
42:
43: public $onQuery;
44:
45:
46:
47: public function __construct($dsn, $username = NULL, $password = NULL, array $options = NULL)
48: {
49: parent::__construct($dsn, $username, $password, $options);
50: $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
51: $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Nette\Database\Statement', array($this)));
52:
53: $class = 'Nette\Database\Drivers\Pdo' . $this->getAttribute(PDO::ATTR_DRIVER_NAME) . 'Driver';
54: if (class_exists($class)) {
55: $this->driver = new $class($this, (array) $options);
56: }
57:
58: $this->preprocessor = new SqlPreprocessor($this);
59:
60: $this->databaseReflection = new Reflection\DatabaseReflection; 61:
62: if (!Nette\Debug::$productionMode) {
63: Nette\Debug::addPanel($panel = new DatabasePanel($dsn));
64: $this->onQuery[] = callback($panel, 'logQuery');
65: }
66: }
67:
68:
69:
70:
71: public function getSupplementalDriver()
72: {
73: return $this->driver;
74: }
75:
76:
77:
78: 79: 80: 81: 82: 83:
84: public function query($statement)
85: {
86: $args = func_get_args();
87: return $this->queryArgs(array_shift($args), $args);
88: }
89:
90:
91:
92: 93: 94: 95: 96: 97:
98: public function exec($statement)
99: {
100: $args = func_get_args();
101: return $this->queryArgs(array_shift($args), $args)->rowCount();
102: }
103:
104:
105:
106: 107: 108: 109: 110:
111: public function queryArgs($statement, $params)
112: {
113: foreach ($params as $value) {
114: if (is_array($value) || is_object($value)) {
115: $need = TRUE; break;
116: }
117: }
118: if (isset($need) || strpos($statement, ':') !== FALSE && $this->preprocessor !== NULL) {
119: list($statement, $params) = $this->preprocessor->process($statement, $params);
120: }
121:
122: return $this->prepare($statement)->execute($params);
123: }
124:
125:
126:
127:
128:
129:
130:
131: 132: 133: 134: 135: 136:
137: public function fetch($args)
138: {
139: $args = func_get_args();
140: return $this->queryArgs(array_shift($args), $args)->fetch();
141: }
142:
143:
144:
145: 146: 147: 148: 149: 150:
151: public function fetchColumn($args)
152: {
153: $args = func_get_args();
154: return $this->queryArgs(array_shift($args), $args)->fetchColumn();
155: }
156:
157:
158:
159: 160: 161: 162: 163: 164:
165: public function fetchPairs($args)
166: {
167: $args = func_get_args();
168: return $this->queryArgs(array_shift($args), $args)->fetchPairs();
169: }
170:
171:
172:
173: 174: 175: 176: 177: 178:
179: public function fetchAll($args)
180: {
181: $args = func_get_args();
182: return $this->queryArgs(array_shift($args), $args)->fetchAll();
183: }
184:
185:
186:
187:
188:
189:
190:
191: 192: 193: 194: 195:
196: public function table($table)
197: {
198: return new Selector\TableSelection($table, $this);
199: }
200:
201:
202:
203:
204:
205:
206:
207: 208: 209: 210: 211:
212: public function loadFile($file)
213: {
214: @set_time_limit(0); 215:
216: $handle = @fopen($file, 'r'); 217: if (!$handle) {
218: throw new \FileNotFoundException("Cannot open file '$file'.");
219: }
220:
221: $count = 0;
222: $sql = '';
223: while (!feof($handle)) {
224: $s = fgets($handle);
225: $sql .= $s;
226: if (substr(rtrim($s), -1) === ';') {
227: parent::exec($sql); 228: $sql = '';
229: $count++;
230: }
231: }
232: fclose($handle);
233: return $count;
234: }
235:
236:
237:
238: 239: 240: 241: 242:
243: public static function highlightSql($sql)
244: {
245: static $keywords1 = 'SELECT|UPDATE|INSERT(?:\s+INTO)?|REPLACE(?:\s+INTO)?|DELETE|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|OFFSET|SET|VALUES|LEFT\s+JOIN|INNER\s+JOIN|TRUNCATE';
246: static $keywords2 = 'ALL|DISTINCT|DISTINCTROW|AS|USING|ON|AND|OR|IN|IS|NOT|NULL|LIKE|TRUE|FALSE';
247:
248: 249: $sql = " $sql ";
250: $sql = preg_replace("#(?<=[\\s,(])($keywords1)(?=[\\s,)])#i", "\n\$1", $sql);
251:
252: 253: $sql = preg_replace('#[ \t]{2,}#', " ", $sql);
254:
255: $sql = wordwrap($sql, 100);
256: $sql = preg_replace("#([ \t]*\r?\n){2,}#", "\n", $sql);
257:
258: 259: $sql = htmlSpecialChars($sql);
260: $sql = preg_replace_callback("#(/\\*.+?\\*/)|(\\*\\*.+?\\*\\*)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(=])($keywords2)(?=[\\s,)=])#is", function($matches) {
261: if (!empty($matches[1])) 262: return '<em style="color:gray">' . $matches[1] . '</em>';
263:
264: if (!empty($matches[2])) 265: return '<strong style="color:red">' . $matches[2] . '</strong>';
266:
267: if (!empty($matches[3])) 268: return '<strong style="color:blue">' . $matches[3] . '</strong>';
269:
270: if (!empty($matches[4])) 271: return '<strong style="color:green">' . $matches[4] . '</strong>';
272: }, $sql);
273:
274: return '<pre class="dump">' . trim($sql) . "</pre>\n";
275: }
276:
277:
278:
279:
280:
281:
282:
283: 284: 285:
286: public static function getReflection()
287: {
288: return new Nette\Reflection\ClassReflection(get_called_class());
289: }
290:
291:
292:
293: public function __call($name, $args)
294: {
295: return ObjectMixin::call($this, $name, $args);
296: }
297:
298:
299:
300: public function &__get($name)
301: {
302: return ObjectMixin::get($this, $name);
303: }
304:
305:
306:
307: public function __set($name, $value)
308: {
309: return ObjectMixin::set($this, $name, $value);
310: }
311:
312:
313:
314: public function __isset($name)
315: {
316: return ObjectMixin::has($this, $name);
317: }
318:
319:
320:
321: public function __unset($name)
322: {
323: ObjectMixin::remove($this, $name);
324: }
325:
326: }
327: