Passed
Pull Request — 2.x (#6)
by Fabrice
03:18
created

PdoUniqueKeyExtractor::fetchJoinedRecords()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 20
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 20
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\NodalFlow\NodalFlowException;
13
use fab2s\NodalFlow\YaEtlException;
14
15
/**
16
 * class PdoUniqueKeyExtractor
17
 */
18
class PdoUniqueKeyExtractor extends UniqueKeyExtractorAbstract
19
{
20
    use PdoExtractorTrait {
21
        fetchRecords as pdoFetchRecords;
22
    }
23
24
    /**
25
     * Generic extraction from tables with unique (composite) key
26
     *
27
     * @param \PDO         $pdo
28
     * @param string|null  $extractQuery
29
     * @param array|string $uniqueKey    can be either a unique key name as
30
     *                                   string
31
     *                                   `'(table.)compositeKeyName' // ('id' by default)`
32
     *
33
     *                      or an array :
34
     *                      `['(table.)compositeKey1'] // single unique key`
35
     *                      `['(table.)compositeKey1', '(table.)compositeKey2', ] // composite unique key`
36
     *
37
     *                      or an associative array in case you are using aliases :
38
     *                      `[
39
     *                          '(table.)compositeKey1' => 'aliasNameAsInRecord',
40
     *                      ]`
41
     *
42
     *                      and :
43
     *                      `[
44
     *                          '(table.)compositeKey1' => 'aliasNameAsInRecord1',
45
     *                          '(table.)compositeKey2' => 'aliasNameAsInRecord2',
46
     *                          // ...
47
     *                      ]`
48
     *
49
     * @throws YaEtlException
50
     * @throws NodalFlowException
51
     */
52
    public function __construct(\PDO $pdo, ?string $extractQuery = null, $uniqueKey = 'id')
53
    {
54
        $this->configurePdo($pdo);
55
56
        parent::__construct($extractQuery, $uniqueKey);
57
    }
58
59
    /**
60
     * Leave no trace
61
     * implement here to allow easier overriding
62
     */
63
    public function __destruct()
64
    {
65
        if ($this->driverBufferedQuery) {
66
            // set driver state back to where we met
67
            $this->pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
68
        }
69
    }
70
71
    /**
72
     * Fetch records
73
     *
74
     * @return bool
75
     */
76
    public function fetchRecords(): bool
77
    {
78
        if (!$this->pdoFetchRecords()) {
79
            return false;
80
        }
81
82
        return true;
83
    }
84
85
    /**
86
     * @return bool
87
     */
88
    protected function fetchJoinedRecords(): bool
89
    {
90
        $extractQuery = $this->getPaginatedQuery();
91
        $statement    = $this->pdo->prepare($extractQuery);
92
        if (!$statement->execute(!empty($this->queryBindings) ? $this->queryBindings : null)) {
93
            return false;
94
        }
95
96
        $this->joinedRecords = [];
97
        while ($record = $statement->fetch(\PDO::FETCH_ASSOC)) {
98
            $this->joinedRecords[$record[$this->uniqueKeyName]] = $record;
99
        }
100
101
        $statement->closeCursor();
102
        unset($statement);
103
        // still set this as extracted as we build
104
        // record map in both from and join context
105
        $this->setExtracted($this->joinedRecords);
106
107
        return !empty($this->joinedRecords);
108
    }
109
110
    /**
111
     * This method sets offset and limit in the query
112
     * WARNING : if you set an offset without limit,
113
     * the limit will be set to  $this->maxdefaultLimit
114
     *
115
     * @return string the paginated query with current offset and limit
116
     */
117
    protected function getPaginatedQuery(): string
118
    {
119
        if ($this->joinFrom) {
120
            $this->queryBindings = array_values($this->uniqueKeyValues);
121
122
            $whereOrAndStr = stripos($this->extractQuery, 'WHERE') !== false ? 'AND' : 'WHERE';
123
124
            return $this->extractQuery . " $whereOrAndStr $this->uniqueKeyName IN (" . implode(',', array_fill(0, count($this->uniqueKeyValues), '?')) . ')';
125
        }
126
127
        return $this->extractQuery . $this->getLimitOffsetBit();
128
    }
129
}
130