Completed
Push — master ( 2560e6...c15c08 )
by Gabriel
01:59 queued 10s
created

TableDumper   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 276
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 36.84%

Importance

Changes 0
Metric Value
wmc 26
lcom 1
cbo 1
dl 0
loc 276
ccs 28
cts 76
cp 0.3684
rs 10
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A withStructure() 0 5 1
A withData() 0 5 1
A withDrop() 0 5 1
A hasStructure() 0 4 1
A hasData() 0 4 1
A hasDrop() 0 4 1
A where() 0 5 1
A getWhere() 0 4 1
A getTable() 0 4 1
A dumpDropStatement() 0 4 1
A dump() 0 17 4
A dumpCreateStatement() 0 8 1
C dumpInsertStatement() 0 72 10
1
<?php
2
namespace Y0lk\SQLDumper;
3
4
use PDO;
5
6
/**
7
 * A TableDumper instance is used to dump a single Table, allowing you to specify certain dump options for this table only
8
 *
9
 * @author Gabriel Jean <[email protected]>
10
 */
11
class TableDumper {
12
13
    /**
14
     * @var Table   Table instance related to this dumper
15
     */
16
    protected $table;
17
18
    /**
19
     * @var boolean Specifies whether to include the table's structure (CREATE statement)
20
     */
21
    protected $withStructure = true;
22
23
    /**
24
     * @var boolean Specifies whether to include the table's data (INSERT statements)
25
     */
26
    protected $withData = true;
27
28
    /**
29
     * @var boolean Specifies whether to include a DROP TABLE statement
30
     */
31
    protected $withDrop = true;
32
33
    /**
34
     * @var string WHERE parameters written as a regular SQL string to select specific data from this table
35
     */
36
    protected $where = '';
37
38
39
    /**
40
     * @param Table Table this dumper will be used for
41
     */
42 54
    public function __construct(Table $table)
43
    {
44 54
        $this->table = $table;
45 54
    }
46
47
    /**
48
     * Specifies whether to include the table's structure (CREATE statement)
49
     * 
50
     * @param  boolean  $withStructure  TRUE to include structure, FALSE otherwise
51
     * 
52
     * @return TableDumper  Returns the TableDumper instance
53
     */
54 9
    public function withStructure(bool $withStructure = true): TableDumper
55
    {
56 9
        $this->withStructure = $withStructure;
57 9
        return $this;
58
    }
59
60
    /**
61
     * Specifies whether to include the table's data (INSERT statements)
62
     * 
63
     * @param  boolean  $withData   TRUE to include data, FALSE otherwise
64
     * 
65
     * @return TableDumper  Returns the TableDumper instance
66
     */
67 6
    public function withData(bool $withData = true): TableDumper
68
    {
69 6
        $this->withData = $withData;
70 6
        return $this;
71
    }
72
73
    /**
74
     * Specifies whether to include a DROP TABLE statement
75
     * 
76
     * @param  boolean  $withDrop   TRUE to include DROP statement, FALSE otherwise
77
     * 
78
     * @return TableDumper  Returns the TableDumper instance
79
     */
80 6
    public function withDrop(bool $withDrop = true): TableDumper
81
    {
82 6
        $this->withDrop = $withDrop;
83 6
        return $this;
84
    }
85
86
    /**
87
     * Returns whether or not this dumper will include the table's structure
88
     * 
89
     * @return boolean Returns TRUE if it includes it, FALSE otherwise
90
     */
91 9
    public function hasStructure(): bool
92
    {
93 9
        return $this->withStructure;
94
    }
95
96
97
    /**
98
     * Returns whether or not this dumper will include the table's data
99
     * 
100
     * @return boolean Returns TRUE if it includes it, FALSE otherwise
101
     */
102 6
    public function hasData(): bool
103
    {
104 6
        return $this->withData;
105
    }
106
107
108
    /**
109
     * Returns whether or not this dumper will include the table's DROP statement
110
     * 
111
     * @return boolean Returns TRUE if it includes it, FALSE otherwise
112
     */
113 9
    public function hasDrop(): bool
114
    {
115 9
        return $this->withDrop;
116
    }
117
118
119
    /**
120
     * Add WHERE parameters to use when dumping the data 
121
     * 
122
     * @param  string   $where_string   SQL string that you would normally write after WHERE keyowrd
123
     * 
124
     * @return TableDumper  Returns the TableDumper instance
125
     */
126 3
    public function where(string $where_string): TableDumper
127
    {
128 3
        $this->where = $where_string;
129 3
        return $this;
130
    }
131
132
    /**
133
     * Get the where param string
134
     * @return string Returns the WHERE param string
135
     */
136 3
    public function getWhere(): string
137
    {
138 3
        return $this->where;
139
    }
140
141
    /**
142
     * Get the Table related to this dumper
143
     * 
144
     * @return Table    Returns the Table instance
145
     */
146 30
    public function getTable(): Table
147
    {
148 30
        return $this->table;
149
    }
150
151
    /**
152
     * Writes the CREATE statement to the dump stream
153
     * 
154
     * @param  PDO      $db     PDO instance to use for DB queries
155
     * @param  resource $stream Stream to write the dump to
156
     * 
157
     * @return void
158
     */
159
    public function dumpCreateStatement(PDO $db, $stream): void 
160
    {
161
        $stmt = $db->query('SHOW CREATE TABLE `'.$this->table->getName().'`');
162
163
        fwrite($stream, $stmt->fetchColumn(1).";\r\n");
164
165
        $stmt->closeCursor();
166
    }
167
168
    /**
169
     * Writes the DROP statement to the dump stream
170
     * 
171
     * @param  resource $stream Stream to write the dump to
172
     * 
173
     * @return void
174
     */
175 3
    public function dumpDropStatement($stream): void
176
    {
177 3
        fwrite($stream, 'DROP TABLE IF EXISTS `'.$this->table->getName()."`;\r\n");
178 3
    }
179
180
    /**
181
     * Writes the INSERT statements to the dump stream
182
     * 
183
     * @param  PDO      $db     PDO instance to use for DB queries
184
     * @param  resource $stream Stream to write the dump to
185
     * 
186
     * @return void
187
     */
188
    public function dumpInsertStatement(PDO $db, $stream): void
189
    {
190
        //Get data from table
191
        $select = 'SELECT * FROM '.$this->table->getName();
192
193
        if (!empty($this->where)) {
194
            $select .= ' WHERE '.$this->where;
195
        }
196
197
        //Add limit
198
        $limit = 1000;
199
        $select .= ' LIMIT :limit OFFSET :offset';
200
201
        $stmt = $db->prepare($select);
202
        $stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
203
204
        $i = 0;
205
        $j = 0;
206
207
        //Dump an INSERT of all rows with paging 
208
        do {    
209
            $stmt->bindValue(':offset', $i*$limit, PDO::PARAM_INT);
210
            $stmt->execute();
211
212
            while (($row = $stmt->fetch(PDO::FETCH_ASSOC)) !== false) {
213
                //Write start of INSERT statement
214
                if ($j === 0) {
215
                    //Gets keys from array indexes of first row
216
                    $listFields = array_keys($row);
217
218
                    //Escape them
219
                    foreach ($listFields as $key => $field) {
220
                        $listFields[$key] = '`'.$field.'`';
221
                    }
222
223
                    $fields = implode(',', $listFields);
224
                    
225
                    fwrite($stream, 'INSERT INTO `'.$this->table->getName().'` ('.$fields.') VALUES ');
226
                }
227
228
                //Write values of this row
229
                $valuesDump = '';
230
231
                if ($j > 0) {
232
                    $valuesDump .= ", \r\n";
233
                }
234
235
                $listValues = array_values($row);
236
237
                //Quote values or replace with NULL if null
238
                foreach ($listValues as $key => $value) {
239
                    $quotedValue = str_replace("'", "\'", str_replace('"', '\"', $value));
240
                    $listValues[$key] = (!isset($value) ? 'NULL' : "'".$quotedValue."'");
241
                }
242
243
                //Add values from this row to valuesDump
244
                $valuesDump .= '('.implode(',', $listValues).')';
245
246
                fwrite($stream, $valuesDump);
247
                $j++;
248
            }
249
250
            $stmt->closeCursor();
251
            $i++;
252
253
        } while ($j === $i*$limit);
254
255
        //If there was at least one row, write end of INSERT statement
256
        if ($j > 0) {
257
            fwrite($stream, ";\r\n");
258
        }
259
    }
260
261
    /**
262
     * Writes all the SQL statements of this dumper to the dump stream
263
     * 
264
     * @param  PDO      $db     PDO instance to use for DB queries
265
     * @param  resource $stream Stream to write the dump to
266
     * 
267
     * @return void
268
     */
269
    public function dump(PDO $db, $stream): void
270
    {
271
        //Drop table statement
272
        if ($this->withDrop) {
273
            $this->dumpDropStatement($stream);
274
        }
275
276
        //Create table statement
277
        if ($this->withStructure) {
278
            $this->dumpCreateStatement($db, $stream);
279
        }
280
281
        //Data
282
        if ($this->withData) {
283
            $this->dumpInsertStatement($db, $stream);
284
        }
285
    }
286
}