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