PdoExtractorTrait::fetchRecords()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 23
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 11
c 0
b 0
f 0
nc 3
nop 0
dl 0
loc 23
rs 9.9
1
<?php
2
3
/*
4
 * This file is part of YaEtl
5
 *     (c) Fabrice de Stefanis / https://github.com/fab2s/YaEtl
6
 * This source file is licensed under the MIT license which you will
7
 * find in the LICENSE file or at https://opensource.org/licenses/MIT
8
 */
9
10
namespace fab2s\YaEtl\Extractors;
11
12
use fab2s\YaEtl\YaEtlException;
13
14
/**
15
 * trait PdoExtractorTrait
16
 */
17
trait PdoExtractorTrait
18
{
19
    /**
20
     * The PDO connection
21
     *
22
     * @var \PDO
23
     */
24
    protected $pdo;
25
26
    /**
27
     * Keep track of Buffered queries status in case we need / can to tweak it
28
     *
29
     * @var bool
30
     */
31
    protected $driverBufferedQuery;
32
33
    /**
34
     * List of supported drivers
35
     *
36
     * @var array
37
     */
38
    protected $supportedDrivers = [
39
        'mysql'  => 'mysql',
40
        'sqlite' => 'sqlite',
41
        'pgsql'  => 'pgsql',
42
    ];
43
44
    /**
45
     * Current driver name
46
     *
47
     * @var string
48
     */
49
    protected $dbDriverName;
50
51
    /**
52
     * Query bindings
53
     *
54
     * @var array
55
     */
56
    protected $queryBindings;
57
58
    /**
59
     * Leave no trace
60
     */
61
    public function __destruct()
62
    {
63
        if ($this->dbDriverName === 'mysql' && $this->driverBufferedQuery) {
64
            // set driver state back to where we met
65
            $this->pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
66
        }
67
    }
68
69
    /**
70
     * Properly set up PDO connection
71
     *
72
     * @param \PDO $pdo
73
     *
74
     * @throws YaEtlException
75
     *
76
     * @return static
77
     */
78
    public function configurePdo(\PDO $pdo): self
79
    {
80
        $this->pdo          = $pdo;
81
        $this->dbDriverName = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
82
83
        if (!($this instanceof PaginatedQueryInterface) && !isset($this->supportedDrivers[$this->dbDriverName])) {
84
            throw new YaEtlException(\get_class($this) . ' does not implement PaginatedQueryInterface and does not uses a supported Pdo driver, supported drivers are: ' . \implode(', ', \array_keys($this->supportedDrivers)));
85
        }
86
87
        if ($this->dbDriverName === 'mysql') {
88
            // buffered queries can have great performance impact
89
            // with large data sets
90
            $this->driverBufferedQuery = $this->pdo->getAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY);
91
92
            if ($this->driverBufferedQuery) {
93
                // disable buffered queries as we should be querying by a lot
94
                $this->pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
95
            }
96
        }
97
98
        return $this;
99
    }
100
101
    /**
102
     * Fetch records
103
     *
104
     * @return bool
105
     */
106
    public function fetchRecords(): bool
107
    {
108
        $extractQuery = $this->getPaginatedQuery();
109
        $statement    = $this->pdo->prepare($extractQuery);
110
        if (!$statement->execute(!empty($this->queryBindings) ? $this->queryBindings : null)) {
111
            return false;
112
        }
113
114
        // It is most likely better to proxy all records
115
        // as it also makes sure that we read from db as
116
        // fast as possible and release pressure asap
117
        $collection = new \SplDoublyLinkedList;
118
        while ($record = $statement->fetch(\PDO::FETCH_ASSOC)) {
119
            $collection->push($record);
120
        }
121
122
        $statement->closeCursor();
123
        unset($statement);
124
125
        /* @var $this DbExtractorAbstract */
126
        $this->setExtractedCollection($collection);
127
128
        return !$collection->isEmpty();
129
    }
130
131
    /**
132
     * @return string the paginated query with current offset and limit
133
     */
134
    abstract public function getPaginatedQuery(): string;
135
}
136