1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15: namespace Cake\Database;
16:
17: use Cake\Database\Query;
18: use Cake\Database\Statement\PDOStatement;
19: use InvalidArgumentException;
20: use PDO;
21: use PDOException;
22:
23: 24: 25: 26:
27: abstract class Driver implements DriverInterface
28: {
29: 30: 31: 32: 33:
34: protected $_connection;
35:
36: 37: 38: 39: 40:
41: protected $_config;
42:
43: 44: 45: 46: 47: 48:
49: protected $_baseConfig = [];
50:
51: 52: 53: 54: 55: 56:
57: protected $_autoQuoting = false;
58:
59: 60: 61: 62: 63: 64:
65: public function __construct($config = [])
66: {
67: if (empty($config['username']) && !empty($config['login'])) {
68: throw new InvalidArgumentException(
69: 'Please pass "username" instead of "login" for connecting to the database'
70: );
71: }
72: $config += $this->_baseConfig;
73: $this->_config = $config;
74: if (!empty($config['quoteIdentifiers'])) {
75: $this->enableAutoQuoting();
76: }
77: }
78:
79: 80: 81: 82: 83: 84: 85:
86: protected function _connect($dsn, array $config)
87: {
88: $connection = new PDO(
89: $dsn,
90: $config['username'],
91: $config['password'],
92: $config['flags']
93: );
94: $this->setConnection($connection);
95:
96: return true;
97: }
98:
99: 100: 101:
102: abstract public function connect();
103:
104: 105: 106:
107: public function disconnect()
108: {
109: $this->_connection = null;
110: }
111:
112: 113: 114: 115: 116: 117: 118: 119: 120:
121: public function connection($connection = null)
122: {
123: deprecationWarning(
124: get_called_class() . '::connection() is deprecated. ' .
125: 'Use setConnection()/getConnection() instead.'
126: );
127: if ($connection !== null) {
128: $this->_connection = $connection;
129: }
130:
131: return $this->_connection;
132: }
133:
134: 135: 136: 137: 138:
139: public function getConnection()
140: {
141: return $this->_connection;
142: }
143:
144: 145: 146: 147: 148: 149:
150: public function setConnection($connection)
151: {
152: $this->_connection = $connection;
153:
154: return $this;
155: }
156:
157: 158: 159:
160: abstract public function enabled();
161:
162: 163: 164:
165: public function prepare($query)
166: {
167: $this->connect();
168: $isObject = $query instanceof Query;
169: $statement = $this->_connection->prepare($isObject ? $query->sql() : $query);
170:
171: return new PDOStatement($statement, $this);
172: }
173:
174: 175: 176:
177: public function beginTransaction()
178: {
179: $this->connect();
180: if ($this->_connection->inTransaction()) {
181: return true;
182: }
183:
184: return $this->_connection->beginTransaction();
185: }
186:
187: 188: 189:
190: public function commitTransaction()
191: {
192: $this->connect();
193: if (!$this->_connection->inTransaction()) {
194: return false;
195: }
196:
197: return $this->_connection->commit();
198: }
199:
200: 201: 202:
203: public function rollbackTransaction()
204: {
205: $this->connect();
206: if (!$this->_connection->inTransaction()) {
207: return false;
208: }
209:
210: return $this->_connection->rollBack();
211: }
212:
213: 214: 215:
216: abstract public function releaseSavePointSQL($name);
217:
218: 219: 220:
221: abstract public function savePointSQL($name);
222:
223: 224: 225:
226: abstract public function rollbackSavePointSQL($name);
227:
228: 229: 230:
231: abstract public function disableForeignKeySQL();
232:
233: 234: 235:
236: abstract public function enableForeignKeySQL();
237:
238: 239: 240:
241: abstract public function supportsDynamicConstraints();
242:
243: 244: 245:
246: public function supportsSavePoints()
247: {
248: return true;
249: }
250:
251: 252: 253:
254: public function quote($value, $type)
255: {
256: $this->connect();
257:
258: return $this->_connection->quote($value, $type);
259: }
260:
261: 262: 263: 264: 265:
266: public function supportsQuoting()
267: {
268: $this->connect();
269:
270: return $this->_connection->getAttribute(PDO::ATTR_DRIVER_NAME) !== 'odbc';
271: }
272:
273: 274: 275:
276: abstract public function queryTranslator($type);
277:
278: 279: 280:
281: abstract public function schemaDialect();
282:
283: 284: 285:
286: abstract public function quoteIdentifier($identifier);
287:
288: 289: 290:
291: public function schemaValue($value)
292: {
293: if ($value === null) {
294: return 'NULL';
295: }
296: if ($value === false) {
297: return 'FALSE';
298: }
299: if ($value === true) {
300: return 'TRUE';
301: }
302: if (is_float($value)) {
303: return str_replace(',', '.', (string)$value);
304: }
305: if ((is_int($value) || $value === '0') || (
306: is_numeric($value) && strpos($value, ',') === false &&
307: $value[0] !== '0' && strpos($value, 'e') === false)
308: ) {
309: return (string)$value;
310: }
311:
312: return $this->_connection->quote($value, PDO::PARAM_STR);
313: }
314:
315: 316: 317:
318: public function schema()
319: {
320: return $this->_config['schema'];
321: }
322:
323: 324: 325:
326: public function lastInsertId($table = null, $column = null)
327: {
328: $this->connect();
329:
330: if ($this->_connection instanceof PDO) {
331: return $this->_connection->lastInsertId($table);
332: }
333:
334: return $this->_connection->lastInsertId($table, $column);
335: }
336:
337: 338: 339:
340: public function isConnected()
341: {
342: if ($this->_connection === null) {
343: $connected = false;
344: } else {
345: try {
346: $connected = $this->_connection->query('SELECT 1');
347: } catch (PDOException $e) {
348: $connected = false;
349: }
350: }
351:
352: return (bool)$connected;
353: }
354:
355: 356: 357:
358: public function enableAutoQuoting($enable = true)
359: {
360: $this->_autoQuoting = (bool)$enable;
361:
362: return $this;
363: }
364:
365: 366: 367: 368: 369:
370: public function disableAutoQuoting()
371: {
372: $this->_autoQuoting = false;
373:
374: return $this;
375: }
376:
377: 378: 379:
380: public function isAutoQuotingEnabled()
381: {
382: return $this->_autoQuoting;
383: }
384:
385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395:
396: public function autoQuoting($enable = null)
397: {
398: deprecationWarning(
399: 'Driver::autoQuoting() is deprecated. ' .
400: 'Use Driver::enableAutoQuoting()/isAutoQuotingEnabled() instead.'
401: );
402: if ($enable !== null) {
403: $this->enableAutoQuoting($enable);
404: }
405:
406: return $this->isAutoQuotingEnabled();
407: }
408:
409: 410: 411:
412: public function compileQuery(Query $query, ValueBinder $generator)
413: {
414: $processor = $this->newCompiler();
415: $translator = $this->queryTranslator($query->type());
416: $query = $translator($query);
417:
418: return [$query, $processor->compile($query, $generator)];
419: }
420:
421: 422: 423:
424: public function newCompiler()
425: {
426: return new QueryCompiler();
427: }
428:
429: 430: 431:
432: public function __destruct()
433: {
434: $this->_connection = null;
435: }
436:
437: 438: 439: 440: 441: 442:
443: public function __debugInfo()
444: {
445: return [
446: 'connected' => $this->_connection !== null
447: ];
448: }
449: }
450: