Projekt

Obecné

Profil

Stáhnout (30.9 KB) Statistiky
| Větev: | Revize:
1
<?php
2

    
3
namespace Illuminate\Database;
4

    
5
use PDO;
6
use Closure;
7
use Exception;
8
use Throwable;
9
use LogicException;
10
use RuntimeException;
11
use DateTimeInterface;
12
use Illuminate\Support\Arr;
13
use Illuminate\Database\Query\Expression;
14
use Illuminate\Contracts\Events\Dispatcher;
15
use Illuminate\Database\Query\Processors\Processor;
16
use Doctrine\DBAL\Connection as DoctrineConnection;
17
use Illuminate\Database\Query\Builder as QueryBuilder;
18
use Illuminate\Database\Schema\Builder as SchemaBuilder;
19
use Illuminate\Database\Query\Grammars\Grammar as QueryGrammar;
20

    
21
class Connection implements ConnectionInterface
22
{
23
    use DetectsLostConnections;
24

    
25
    /**
26
     * The active PDO connection.
27
     *
28
     * @var PDO
29
     */
30
    protected $pdo;
31

    
32
    /**
33
     * The active PDO connection used for reads.
34
     *
35
     * @var PDO
36
     */
37
    protected $readPdo;
38

    
39
    /**
40
     * The reconnector instance for the connection.
41
     *
42
     * @var callable
43
     */
44
    protected $reconnector;
45

    
46
    /**
47
     * The query grammar implementation.
48
     *
49
     * @var \Illuminate\Database\Query\Grammars\Grammar
50
     */
51
    protected $queryGrammar;
52

    
53
    /**
54
     * The schema grammar implementation.
55
     *
56
     * @var \Illuminate\Database\Schema\Grammars\Grammar
57
     */
58
    protected $schemaGrammar;
59

    
60
    /**
61
     * The query post processor implementation.
62
     *
63
     * @var \Illuminate\Database\Query\Processors\Processor
64
     */
65
    protected $postProcessor;
66

    
67
    /**
68
     * The event dispatcher instance.
69
     *
70
     * @var \Illuminate\Contracts\Events\Dispatcher
71
     */
72
    protected $events;
73

    
74
    /**
75
     * The default fetch mode of the connection.
76
     *
77
     * @var int
78
     */
79
    protected $fetchMode = PDO::FETCH_OBJ;
80

    
81
    /**
82
     * The argument for the fetch mode.
83
     *
84
     * @var mixed
85
     */
86
    protected $fetchArgument;
87

    
88
    /**
89
     * The constructor arguments for the PDO::FETCH_CLASS fetch mode.
90
     *
91
     * @var array
92
     */
93
    protected $fetchConstructorArgument = [];
94

    
95
    /**
96
     * The number of active transactions.
97
     *
98
     * @var int
99
     */
100
    protected $transactions = 0;
101

    
102
    /**
103
     * All of the queries run against the connection.
104
     *
105
     * @var array
106
     */
107
    protected $queryLog = [];
108

    
109
    /**
110
     * Indicates whether queries are being logged.
111
     *
112
     * @var bool
113
     */
114
    protected $loggingQueries = false;
115

    
116
    /**
117
     * Indicates if the connection is in a "dry run".
118
     *
119
     * @var bool
120
     */
121
    protected $pretending = false;
122

    
123
    /**
124
     * The name of the connected database.
125
     *
126
     * @var string
127
     */
128
    protected $database;
129

    
130
    /**
131
     * The instance of Doctrine connection.
132
     *
133
     * @var \Doctrine\DBAL\Connection
134
     */
135
    protected $doctrineConnection;
136

    
137
    /**
138
     * The table prefix for the connection.
139
     *
140
     * @var string
141
     */
142
    protected $tablePrefix = '';
143

    
144
    /**
145
     * The database connection configuration options.
146
     *
147
     * @var array
148
     */
149
    protected $config = [];
150

    
151
    /**
152
     * Create a new database connection instance.
153
     *
154
     * @param  \PDO|\Closure     $pdo
155
     * @param  string   $database
156
     * @param  string   $tablePrefix
157
     * @param  array    $config
158
     * @return void
159
     */
160
    public function __construct($pdo, $database = '', $tablePrefix = '', array $config = [])
161
    {
162
        $this->pdo = $pdo;
163

    
164
        // First we will setup the default properties. We keep track of the DB
165
        // name we are connected to since it is needed when some reflective
166
        // type commands are run such as checking whether a table exists.
167
        $this->database = $database;
168

    
169
        $this->tablePrefix = $tablePrefix;
170

    
171
        $this->config = $config;
172

    
173
        // We need to initialize a query grammar and the query post processors
174
        // which are both very important parts of the database abstractions
175
        // so we initialize these to their default values while starting.
176
        $this->useDefaultQueryGrammar();
177

    
178
        $this->useDefaultPostProcessor();
179
    }
180

    
181
    /**
182
     * Set the query grammar to the default implementation.
183
     *
184
     * @return void
185
     */
186
    public function useDefaultQueryGrammar()
187
    {
188
        $this->queryGrammar = $this->getDefaultQueryGrammar();
189
    }
190

    
191
    /**
192
     * Get the default query grammar instance.
193
     *
194
     * @return \Illuminate\Database\Query\Grammars\Grammar
195
     */
196
    protected function getDefaultQueryGrammar()
197
    {
198
        return new QueryGrammar;
199
    }
200

    
201
    /**
202
     * Set the schema grammar to the default implementation.
203
     *
204
     * @return void
205
     */
206
    public function useDefaultSchemaGrammar()
207
    {
208
        $this->schemaGrammar = $this->getDefaultSchemaGrammar();
209
    }
210

    
211
    /**
212
     * Get the default schema grammar instance.
213
     *
214
     * @return \Illuminate\Database\Schema\Grammars\Grammar
215
     */
216
    protected function getDefaultSchemaGrammar()
217
    {
218
        //
219
    }
220

    
221
    /**
222
     * Set the query post processor to the default implementation.
223
     *
224
     * @return void
225
     */
226
    public function useDefaultPostProcessor()
227
    {
228
        $this->postProcessor = $this->getDefaultPostProcessor();
229
    }
230

    
231
    /**
232
     * Get the default post processor instance.
233
     *
234
     * @return \Illuminate\Database\Query\Processors\Processor
235
     */
236
    protected function getDefaultPostProcessor()
237
    {
238
        return new Processor;
239
    }
240

    
241
    /**
242
     * Get a schema builder instance for the connection.
243
     *
244
     * @return \Illuminate\Database\Schema\Builder
245
     */
246
    public function getSchemaBuilder()
247
    {
248
        if (is_null($this->schemaGrammar)) {
249
            $this->useDefaultSchemaGrammar();
250
        }
251

    
252
        return new SchemaBuilder($this);
253
    }
254

    
255
    /**
256
     * Begin a fluent query against a database table.
257
     *
258
     * @param  string  $table
259
     * @return \Illuminate\Database\Query\Builder
260
     */
261
    public function table($table)
262
    {
263
        return $this->query()->from($table);
264
    }
265

    
266
    /**
267
     * Get a new query builder instance.
268
     *
269
     * @return \Illuminate\Database\Query\Builder
270
     */
271
    public function query()
272
    {
273
        return new QueryBuilder(
274
            $this, $this->getQueryGrammar(), $this->getPostProcessor()
275
        );
276
    }
277

    
278
    /**
279
     * Get a new raw query expression.
280
     *
281
     * @param  mixed  $value
282
     * @return \Illuminate\Database\Query\Expression
283
     */
284
    public function raw($value)
285
    {
286
        return new Expression($value);
287
    }
288

    
289
    /**
290
     * Run a select statement and return a single result.
291
     *
292
     * @param  string  $query
293
     * @param  array   $bindings
294
     * @return mixed
295
     */
296
    public function selectOne($query, $bindings = [])
297
    {
298
        $records = $this->select($query, $bindings);
299

    
300
        return count($records) > 0 ? reset($records) : null;
301
    }
302

    
303
    /**
304
     * Run a select statement against the database.
305
     *
306
     * @param  string  $query
307
     * @param  array   $bindings
308
     * @return array
309
     */
310
    public function selectFromWriteConnection($query, $bindings = [])
311
    {
312
        return $this->select($query, $bindings, false);
313
    }
314

    
315
    /**
316
     * Run a select statement against the database.
317
     *
318
     * @param  string  $query
319
     * @param  array  $bindings
320
     * @param  bool  $useReadPdo
321
     * @return array
322
     */
323
    public function select($query, $bindings = [], $useReadPdo = true)
324
    {
325
        return $this->run($query, $bindings, function ($me, $query, $bindings) use ($useReadPdo) {
326
            if ($me->pretending()) {
327
                return [];
328
            }
329

    
330
            // For select statements, we'll simply execute the query and return an array
331
            // of the database result set. Each element in the array will be a single
332
            // row from the database table, and will either be an array or objects.
333
            $statement = $this->getPdoForSelect($useReadPdo)->prepare($query);
334

    
335
            $statement->execute($me->prepareBindings($bindings));
336

    
337
            $fetchMode = $me->getFetchMode();
338
            $fetchArgument = $me->getFetchArgument();
339
            $fetchConstructorArgument = $me->getFetchConstructorArgument();
340

    
341
            if ($fetchMode === PDO::FETCH_CLASS && ! isset($fetchArgument)) {
342
                $fetchArgument = 'StdClass';
343
                $fetchConstructorArgument = null;
344
            }
345

    
346
            return isset($fetchArgument)
347
                ? $statement->fetchAll($fetchMode, $fetchArgument, $fetchConstructorArgument)
348
                : $statement->fetchAll($fetchMode);
349
        });
350
    }
351

    
352
    /**
353
     * Run a select statement against the database and returns a generator.
354
     *
355
     * @param  string  $query
356
     * @param  array  $bindings
357
     * @param  bool  $useReadPdo
358
     * @return \Generator
359
     */
360
    public function cursor($query, $bindings = [], $useReadPdo = true)
361
    {
362
        $statement = $this->run($query, $bindings, function ($me, $query, $bindings) use ($useReadPdo) {
363
            if ($me->pretending()) {
364
                return [];
365
            }
366

    
367
            $statement = $this->getPdoForSelect($useReadPdo)->prepare($query);
368

    
369
            $fetchMode = $me->getFetchMode();
370
            $fetchArgument = $me->getFetchArgument();
371
            $fetchConstructorArgument = $me->getFetchConstructorArgument();
372

    
373
            if ($fetchMode === PDO::FETCH_CLASS && ! isset($fetchArgument)) {
374
                $fetchArgument = 'StdClass';
375
                $fetchConstructorArgument = null;
376
            }
377

    
378
            if (isset($fetchArgument)) {
379
                $statement->setFetchMode($fetchMode, $fetchArgument, $fetchConstructorArgument);
380
            } else {
381
                $statement->setFetchMode($fetchMode);
382
            }
383

    
384
            $statement->execute($me->prepareBindings($bindings));
385

    
386
            return $statement;
387
        });
388

    
389
        while ($record = $statement->fetch()) {
390
            yield $record;
391
        }
392
    }
393

    
394
    /**
395
     * Get the PDO connection to use for a select query.
396
     *
397
     * @param  bool  $useReadPdo
398
     * @return \PDO
399
     */
400
    protected function getPdoForSelect($useReadPdo = true)
401
    {
402
        return $useReadPdo ? $this->getReadPdo() : $this->getPdo();
403
    }
404

    
405
    /**
406
     * Run an insert statement against the database.
407
     *
408
     * @param  string  $query
409
     * @param  array   $bindings
410
     * @return bool
411
     */
412
    public function insert($query, $bindings = [])
413
    {
414
        return $this->statement($query, $bindings);
415
    }
416

    
417
    /**
418
     * Run an update statement against the database.
419
     *
420
     * @param  string  $query
421
     * @param  array   $bindings
422
     * @return int
423
     */
424
    public function update($query, $bindings = [])
425
    {
426
        return $this->affectingStatement($query, $bindings);
427
    }
428

    
429
    /**
430
     * Run a delete statement against the database.
431
     *
432
     * @param  string  $query
433
     * @param  array   $bindings
434
     * @return int
435
     */
436
    public function delete($query, $bindings = [])
437
    {
438
        return $this->affectingStatement($query, $bindings);
439
    }
440

    
441
    /**
442
     * Execute an SQL statement and return the boolean result.
443
     *
444
     * @param  string  $query
445
     * @param  array   $bindings
446
     * @return bool
447
     */
448
    public function statement($query, $bindings = [])
449
    {
450
        return $this->run($query, $bindings, function ($me, $query, $bindings) {
451
            if ($me->pretending()) {
452
                return true;
453
            }
454

    
455
            $bindings = $me->prepareBindings($bindings);
456

    
457
            return $me->getPdo()->prepare($query)->execute($bindings);
458
        });
459
    }
460

    
461
    /**
462
     * Run an SQL statement and get the number of rows affected.
463
     *
464
     * @param  string  $query
465
     * @param  array   $bindings
466
     * @return int
467
     */
468
    public function affectingStatement($query, $bindings = [])
469
    {
470
        return $this->run($query, $bindings, function ($me, $query, $bindings) {
471
            if ($me->pretending()) {
472
                return 0;
473
            }
474

    
475
            // For update or delete statements, we want to get the number of rows affected
476
            // by the statement and return that back to the developer. We'll first need
477
            // to execute the statement and then we'll use PDO to fetch the affected.
478
            $statement = $me->getPdo()->prepare($query);
479

    
480
            $statement->execute($me->prepareBindings($bindings));
481

    
482
            return $statement->rowCount();
483
        });
484
    }
485

    
486
    /**
487
     * Run a raw, unprepared query against the PDO connection.
488
     *
489
     * @param  string  $query
490
     * @return bool
491
     */
492
    public function unprepared($query)
493
    {
494
        return $this->run($query, [], function ($me, $query) {
495
            if ($me->pretending()) {
496
                return true;
497
            }
498

    
499
            return (bool) $me->getPdo()->exec($query);
500
        });
501
    }
502

    
503
    /**
504
     * Prepare the query bindings for execution.
505
     *
506
     * @param  array  $bindings
507
     * @return array
508
     */
509
    public function prepareBindings(array $bindings)
510
    {
511
        $grammar = $this->getQueryGrammar();
512

    
513
        foreach ($bindings as $key => $value) {
514
            // We need to transform all instances of DateTimeInterface into the actual
515
            // date string. Each query grammar maintains its own date string format
516
            // so we'll just ask the grammar for the format to get from the date.
517
            if ($value instanceof DateTimeInterface) {
518
                $bindings[$key] = $value->format($grammar->getDateFormat());
519
            } elseif ($value === false) {
520
                $bindings[$key] = 0;
521
            }
522
        }
523

    
524
        return $bindings;
525
    }
526

    
527
    /**
528
     * Execute a Closure within a transaction.
529
     *
530
     * @param  \Closure  $callback
531
     * @return mixed
532
     *
533
     * @throws \Exception|\Throwable
534
     */
535
    public function transaction(Closure $callback)
536
    {
537
        $this->beginTransaction();
538

    
539
        // We'll simply execute the given callback within a try / catch block
540
        // and if we catch any exception we can rollback the transaction
541
        // so that none of the changes are persisted to the database.
542
        try {
543
            $result = $callback($this);
544

    
545
            $this->commit();
546
        }
547

    
548
        // If we catch an exception, we will roll back so nothing gets messed
549
        // up in the database. Then we'll re-throw the exception so it can
550
        // be handled how the developer sees fit for their applications.
551
        catch (Exception $e) {
552
            $this->rollBack();
553

    
554
            throw $e;
555
        } catch (Throwable $e) {
556
            $this->rollBack();
557

    
558
            throw $e;
559
        }
560

    
561
        return $result;
562
    }
563

    
564
    /**
565
     * Start a new database transaction.
566
     *
567
     * @return void
568
     * @throws Exception
569
     */
570
    public function beginTransaction()
571
    {
572
        ++$this->transactions;
573

    
574
        if ($this->transactions == 1) {
575
            try {
576
                $this->getPdo()->beginTransaction();
577
            } catch (Exception $e) {
578
                --$this->transactions;
579

    
580
                throw $e;
581
            }
582
        } elseif ($this->transactions > 1 && $this->queryGrammar->supportsSavepoints()) {
583
            $this->getPdo()->exec(
584
                $this->queryGrammar->compileSavepoint('trans'.$this->transactions)
585
            );
586
        }
587

    
588
        $this->fireConnectionEvent('beganTransaction');
589
    }
590

    
591
    /**
592
     * Commit the active database transaction.
593
     *
594
     * @return void
595
     */
596
    public function commit()
597
    {
598
        if ($this->transactions == 1) {
599
            $this->getPdo()->commit();
600
        }
601

    
602
        $this->transactions = max(0, $this->transactions - 1);
603

    
604
        $this->fireConnectionEvent('committed');
605
    }
606

    
607
    /**
608
     * Rollback the active database transaction.
609
     *
610
     * @return void
611
     */
612
    public function rollBack()
613
    {
614
        if ($this->transactions == 1) {
615
            $this->getPdo()->rollBack();
616
        } elseif ($this->transactions > 1 && $this->queryGrammar->supportsSavepoints()) {
617
            $this->getPdo()->exec(
618
                $this->queryGrammar->compileSavepointRollBack('trans'.$this->transactions)
619
            );
620
        }
621

    
622
        $this->transactions = max(0, $this->transactions - 1);
623

    
624
        $this->fireConnectionEvent('rollingBack');
625
    }
626

    
627
    /**
628
     * Get the number of active transactions.
629
     *
630
     * @return int
631
     */
632
    public function transactionLevel()
633
    {
634
        return $this->transactions;
635
    }
636

    
637
    /**
638
     * Execute the given callback in "dry run" mode.
639
     *
640
     * @param  \Closure  $callback
641
     * @return array
642
     */
643
    public function pretend(Closure $callback)
644
    {
645
        $loggingQueries = $this->loggingQueries;
646

    
647
        $this->enableQueryLog();
648

    
649
        $this->pretending = true;
650

    
651
        $this->queryLog = [];
652

    
653
        // Basically to make the database connection "pretend", we will just return
654
        // the default values for all the query methods, then we will return an
655
        // array of queries that were "executed" within the Closure callback.
656
        $callback($this);
657

    
658
        $this->pretending = false;
659

    
660
        $this->loggingQueries = $loggingQueries;
661

    
662
        return $this->queryLog;
663
    }
664

    
665
    /**
666
     * Run a SQL statement and log its execution context.
667
     *
668
     * @param  string    $query
669
     * @param  array     $bindings
670
     * @param  \Closure  $callback
671
     * @return mixed
672
     *
673
     * @throws \Illuminate\Database\QueryException
674
     */
675
    protected function run($query, $bindings, Closure $callback)
676
    {
677
        $this->reconnectIfMissingConnection();
678

    
679
        $start = microtime(true);
680

    
681
        // Here we will run this query. If an exception occurs we'll determine if it was
682
        // caused by a connection that has been lost. If that is the cause, we'll try
683
        // to re-establish connection and re-run the query with a fresh connection.
684
        try {
685
            $result = $this->runQueryCallback($query, $bindings, $callback);
686
        } catch (QueryException $e) {
687
            if ($this->transactions >= 1) {
688
                throw $e;
689
            }
690

    
691
            $result = $this->tryAgainIfCausedByLostConnection(
692
                $e, $query, $bindings, $callback
693
            );
694
        }
695

    
696
        // Once we have run the query we will calculate the time that it took to run and
697
        // then log the query, bindings, and execution time so we will report them on
698
        // the event that the developer needs them. We'll log time in milliseconds.
699
        $time = $this->getElapsedTime($start);
700

    
701
        $this->logQuery($query, $bindings, $time);
702

    
703
        return $result;
704
    }
705

    
706
    /**
707
     * Run a SQL statement.
708
     *
709
     * @param  string    $query
710
     * @param  array     $bindings
711
     * @param  \Closure  $callback
712
     * @return mixed
713
     *
714
     * @throws \Illuminate\Database\QueryException
715
     */
716
    protected function runQueryCallback($query, $bindings, Closure $callback)
717
    {
718
        // To execute the statement, we'll simply call the callback, which will actually
719
        // run the SQL against the PDO connection. Then we can calculate the time it
720
        // took to execute and log the query SQL, bindings and time in our memory.
721
        try {
722
            $result = $callback($this, $query, $bindings);
723
        }
724

    
725
        // If an exception occurs when attempting to run a query, we'll format the error
726
        // message to include the bindings with SQL, which will make this exception a
727
        // lot more helpful to the developer instead of just the database's errors.
728
        catch (Exception $e) {
729
            throw new QueryException(
730
                $query, $this->prepareBindings($bindings), $e
731
            );
732
        }
733

    
734
        return $result;
735
    }
736

    
737
    /**
738
     * Handle a query exception that occurred during query execution.
739
     *
740
     * @param  \Illuminate\Database\QueryException  $e
741
     * @param  string    $query
742
     * @param  array     $bindings
743
     * @param  \Closure  $callback
744
     * @return mixed
745
     *
746
     * @throws \Illuminate\Database\QueryException
747
     */
748
    protected function tryAgainIfCausedByLostConnection(QueryException $e, $query, $bindings, Closure $callback)
749
    {
750
        if ($this->causedByLostConnection($e->getPrevious())) {
751
            $this->reconnect();
752

    
753
            return $this->runQueryCallback($query, $bindings, $callback);
754
        }
755

    
756
        throw $e;
757
    }
758

    
759
    /**
760
     * Disconnect from the underlying PDO connection.
761
     *
762
     * @return void
763
     */
764
    public function disconnect()
765
    {
766
        $this->setPdo(null)->setReadPdo(null);
767
    }
768

    
769
    /**
770
     * Reconnect to the database.
771
     *
772
     * @return void
773
     *
774
     * @throws \LogicException
775
     */
776
    public function reconnect()
777
    {
778
        if (is_callable($this->reconnector)) {
779
            return call_user_func($this->reconnector, $this);
780
        }
781

    
782
        throw new LogicException('Lost connection and no reconnector available.');
783
    }
784

    
785
    /**
786
     * Reconnect to the database if a PDO connection is missing.
787
     *
788
     * @return void
789
     */
790
    protected function reconnectIfMissingConnection()
791
    {
792
        if (is_null($this->getPdo()) || is_null($this->getReadPdo())) {
793
            $this->reconnect();
794
        }
795
    }
796

    
797
    /**
798
     * Log a query in the connection's query log.
799
     *
800
     * @param  string  $query
801
     * @param  array   $bindings
802
     * @param  float|null  $time
803
     * @return void
804
     */
805
    public function logQuery($query, $bindings, $time = null)
806
    {
807
        if (isset($this->events)) {
808
            $this->events->fire(new Events\QueryExecuted(
809
                $query, $bindings, $time, $this
810
            ));
811
        }
812

    
813
        if ($this->loggingQueries) {
814
            $this->queryLog[] = compact('query', 'bindings', 'time');
815
        }
816
    }
817

    
818
    /**
819
     * Register a database query listener with the connection.
820
     *
821
     * @param  \Closure  $callback
822
     * @return void
823
     */
824
    public function listen(Closure $callback)
825
    {
826
        if (isset($this->events)) {
827
            $this->events->listen(Events\QueryExecuted::class, $callback);
828
        }
829
    }
830

    
831
    /**
832
     * Fire an event for this connection.
833
     *
834
     * @param  string  $event
835
     * @return void
836
     */
837
    protected function fireConnectionEvent($event)
838
    {
839
        if (! isset($this->events)) {
840
            return;
841
        }
842

    
843
        switch ($event) {
844
            case 'beganTransaction':
845
                return $this->events->fire(new Events\TransactionBeginning($this));
846
            case 'committed':
847
                return $this->events->fire(new Events\TransactionCommitted($this));
848
            case 'rollingBack':
849
                return $this->events->fire(new Events\TransactionRolledBack($this));
850
        }
851
    }
852

    
853
    /**
854
     * Get the elapsed time since a given starting point.
855
     *
856
     * @param  int    $start
857
     * @return float
858
     */
859
    protected function getElapsedTime($start)
860
    {
861
        return round((microtime(true) - $start) * 1000, 2);
862
    }
863

    
864
    /**
865
     * Is Doctrine available?
866
     *
867
     * @return bool
868
     */
869
    public function isDoctrineAvailable()
870
    {
871
        return class_exists('Doctrine\DBAL\Connection');
872
    }
873

    
874
    /**
875
     * Get a Doctrine Schema Column instance.
876
     *
877
     * @param  string  $table
878
     * @param  string  $column
879
     * @return \Doctrine\DBAL\Schema\Column
880
     */
881
    public function getDoctrineColumn($table, $column)
882
    {
883
        $schema = $this->getDoctrineSchemaManager();
884

    
885
        return $schema->listTableDetails($table)->getColumn($column);
886
    }
887

    
888
    /**
889
     * Get the Doctrine DBAL schema manager for the connection.
890
     *
891
     * @return \Doctrine\DBAL\Schema\AbstractSchemaManager
892
     */
893
    public function getDoctrineSchemaManager()
894
    {
895
        return $this->getDoctrineDriver()->getSchemaManager($this->getDoctrineConnection());
896
    }
897

    
898
    /**
899
     * Get the Doctrine DBAL database connection instance.
900
     *
901
     * @return \Doctrine\DBAL\Connection
902
     */
903
    public function getDoctrineConnection()
904
    {
905
        if (is_null($this->doctrineConnection)) {
906
            $driver = $this->getDoctrineDriver();
907

    
908
            $data = ['pdo' => $this->getPdo(), 'dbname' => $this->getConfig('database')];
909

    
910
            $this->doctrineConnection = new DoctrineConnection($data, $driver);
911
        }
912

    
913
        return $this->doctrineConnection;
914
    }
915

    
916
    /**
917
     * Get the current PDO connection.
918
     *
919
     * @return \PDO
920
     */
921
    public function getPdo()
922
    {
923
        if ($this->pdo instanceof Closure) {
924
            return $this->pdo = call_user_func($this->pdo);
925
        }
926

    
927
        return $this->pdo;
928
    }
929

    
930
    /**
931
     * Get the current PDO connection used for reading.
932
     *
933
     * @return \PDO
934
     */
935
    public function getReadPdo()
936
    {
937
        if ($this->transactions >= 1) {
938
            return $this->getPdo();
939
        }
940

    
941
        return $this->readPdo ?: $this->getPdo();
942
    }
943

    
944
    /**
945
     * Set the PDO connection.
946
     *
947
     * @param  \PDO|null  $pdo
948
     * @return $this
949
     *
950
     * @throws \RuntimeException
951
     */
952
    public function setPdo($pdo)
953
    {
954
        if ($this->transactions >= 1) {
955
            throw new RuntimeException("Can't swap PDO instance while within transaction.");
956
        }
957

    
958
        $this->pdo = $pdo;
959

    
960
        return $this;
961
    }
962

    
963
    /**
964
     * Set the PDO connection used for reading.
965
     *
966
     * @param  \PDO|null  $pdo
967
     * @return $this
968
     */
969
    public function setReadPdo($pdo)
970
    {
971
        $this->readPdo = $pdo;
972

    
973
        return $this;
974
    }
975

    
976
    /**
977
     * Set the reconnect instance on the connection.
978
     *
979
     * @param  callable  $reconnector
980
     * @return $this
981
     */
982
    public function setReconnector(callable $reconnector)
983
    {
984
        $this->reconnector = $reconnector;
985

    
986
        return $this;
987
    }
988

    
989
    /**
990
     * Get the database connection name.
991
     *
992
     * @return string|null
993
     */
994
    public function getName()
995
    {
996
        return $this->getConfig('name');
997
    }
998

    
999
    /**
1000
     * Get an option from the configuration options.
1001
     *
1002
     * @param  string  $option
1003
     * @return mixed
1004
     */
1005
    public function getConfig($option)
1006
    {
1007
        return Arr::get($this->config, $option);
1008
    }
1009

    
1010
    /**
1011
     * Get the PDO driver name.
1012
     *
1013
     * @return string
1014
     */
1015
    public function getDriverName()
1016
    {
1017
        return $this->getConfig('driver');
1018
    }
1019

    
1020
    /**
1021
     * Get the query grammar used by the connection.
1022
     *
1023
     * @return \Illuminate\Database\Query\Grammars\Grammar
1024
     */
1025
    public function getQueryGrammar()
1026
    {
1027
        return $this->queryGrammar;
1028
    }
1029

    
1030
    /**
1031
     * Set the query grammar used by the connection.
1032
     *
1033
     * @param  \Illuminate\Database\Query\Grammars\Grammar  $grammar
1034
     * @return void
1035
     */
1036
    public function setQueryGrammar(Query\Grammars\Grammar $grammar)
1037
    {
1038
        $this->queryGrammar = $grammar;
1039
    }
1040

    
1041
    /**
1042
     * Get the schema grammar used by the connection.
1043
     *
1044
     * @return \Illuminate\Database\Schema\Grammars\Grammar
1045
     */
1046
    public function getSchemaGrammar()
1047
    {
1048
        return $this->schemaGrammar;
1049
    }
1050

    
1051
    /**
1052
     * Set the schema grammar used by the connection.
1053
     *
1054
     * @param  \Illuminate\Database\Schema\Grammars\Grammar  $grammar
1055
     * @return void
1056
     */
1057
    public function setSchemaGrammar(Schema\Grammars\Grammar $grammar)
1058
    {
1059
        $this->schemaGrammar = $grammar;
1060
    }
1061

    
1062
    /**
1063
     * Get the query post processor used by the connection.
1064
     *
1065
     * @return \Illuminate\Database\Query\Processors\Processor
1066
     */
1067
    public function getPostProcessor()
1068
    {
1069
        return $this->postProcessor;
1070
    }
1071

    
1072
    /**
1073
     * Set the query post processor used by the connection.
1074
     *
1075
     * @param  \Illuminate\Database\Query\Processors\Processor  $processor
1076
     * @return void
1077
     */
1078
    public function setPostProcessor(Processor $processor)
1079
    {
1080
        $this->postProcessor = $processor;
1081
    }
1082

    
1083
    /**
1084
     * Get the event dispatcher used by the connection.
1085
     *
1086
     * @return \Illuminate\Contracts\Events\Dispatcher
1087
     */
1088
    public function getEventDispatcher()
1089
    {
1090
        return $this->events;
1091
    }
1092

    
1093
    /**
1094
     * Set the event dispatcher instance on the connection.
1095
     *
1096
     * @param  \Illuminate\Contracts\Events\Dispatcher  $events
1097
     * @return void
1098
     */
1099
    public function setEventDispatcher(Dispatcher $events)
1100
    {
1101
        $this->events = $events;
1102
    }
1103

    
1104
    /**
1105
     * Determine if the connection in a "dry run".
1106
     *
1107
     * @return bool
1108
     */
1109
    public function pretending()
1110
    {
1111
        return $this->pretending === true;
1112
    }
1113

    
1114
    /**
1115
     * Get the default fetch mode for the connection.
1116
     *
1117
     * @return int
1118
     */
1119
    public function getFetchMode()
1120
    {
1121
        return $this->fetchMode;
1122
    }
1123

    
1124
    /**
1125
     * Get the fetch argument to be applied when selecting.
1126
     *
1127
     * @return mixed
1128
     */
1129
    public function getFetchArgument()
1130
    {
1131
        return $this->fetchArgument;
1132
    }
1133

    
1134
    /**
1135
     * Get custom constructor arguments for the PDO::FETCH_CLASS fetch mode.
1136
     *
1137
     * @return array
1138
     */
1139
    public function getFetchConstructorArgument()
1140
    {
1141
        return $this->fetchConstructorArgument;
1142
    }
1143

    
1144
    /**
1145
     * Set the default fetch mode for the connection, and optional arguments for the given fetch mode.
1146
     *
1147
     * @param  int  $fetchMode
1148
     * @param  mixed  $fetchArgument
1149
     * @param  array  $fetchConstructorArgument
1150
     * @return int
1151
     */
1152
    public function setFetchMode($fetchMode, $fetchArgument = null, array $fetchConstructorArgument = [])
1153
    {
1154
        $this->fetchMode = $fetchMode;
1155
        $this->fetchArgument = $fetchArgument;
1156
        $this->fetchConstructorArgument = $fetchConstructorArgument;
1157
    }
1158

    
1159
    /**
1160
     * Get the connection query log.
1161
     *
1162
     * @return array
1163
     */
1164
    public function getQueryLog()
1165
    {
1166
        return $this->queryLog;
1167
    }
1168

    
1169
    /**
1170
     * Clear the query log.
1171
     *
1172
     * @return void
1173
     */
1174
    public function flushQueryLog()
1175
    {
1176
        $this->queryLog = [];
1177
    }
1178

    
1179
    /**
1180
     * Enable the query log on the connection.
1181
     *
1182
     * @return void
1183
     */
1184
    public function enableQueryLog()
1185
    {
1186
        $this->loggingQueries = true;
1187
    }
1188

    
1189
    /**
1190
     * Disable the query log on the connection.
1191
     *
1192
     * @return void
1193
     */
1194
    public function disableQueryLog()
1195
    {
1196
        $this->loggingQueries = false;
1197
    }
1198

    
1199
    /**
1200
     * Determine whether we're logging queries.
1201
     *
1202
     * @return bool
1203
     */
1204
    public function logging()
1205
    {
1206
        return $this->loggingQueries;
1207
    }
1208

    
1209
    /**
1210
     * Get the name of the connected database.
1211
     *
1212
     * @return string
1213
     */
1214
    public function getDatabaseName()
1215
    {
1216
        return $this->database;
1217
    }
1218

    
1219
    /**
1220
     * Set the name of the connected database.
1221
     *
1222
     * @param  string  $database
1223
     * @return string
1224
     */
1225
    public function setDatabaseName($database)
1226
    {
1227
        $this->database = $database;
1228
    }
1229

    
1230
    /**
1231
     * Get the table prefix for the connection.
1232
     *
1233
     * @return string
1234
     */
1235
    public function getTablePrefix()
1236
    {
1237
        return $this->tablePrefix;
1238
    }
1239

    
1240
    /**
1241
     * Set the table prefix in use by the connection.
1242
     *
1243
     * @param  string  $prefix
1244
     * @return void
1245
     */
1246
    public function setTablePrefix($prefix)
1247
    {
1248
        $this->tablePrefix = $prefix;
1249

    
1250
        $this->getQueryGrammar()->setTablePrefix($prefix);
1251
    }
1252

    
1253
    /**
1254
     * Set the table prefix and return the grammar.
1255
     *
1256
     * @param  \Illuminate\Database\Grammar  $grammar
1257
     * @return \Illuminate\Database\Grammar
1258
     */
1259
    public function withTablePrefix(Grammar $grammar)
1260
    {
1261
        $grammar->setTablePrefix($this->tablePrefix);
1262

    
1263
        return $grammar;
1264
    }
1265
}
(1-1/18)