Passed
Push — 3.x ( 84b0a1...b6a0a4 )
by Akihito
01:56 queued 13s
created

Insert   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 330
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 24
eloc 58
c 1
b 0
f 0
dl 0
loc 330
ccs 63
cts 63
cp 1
rs 10

13 Methods

Rating   Name   Duplication   Size   Complexity  
A into() 0 5 1
A cols() 0 3 1
A build() 0 14 2
A col() 0 3 1
A getBindValues() 0 3 1
A getLastInsertIdName() 0 5 2
A set() 0 3 1
A setLastInsertIdNames() 0 3 1
A addRow() 0 14 3
A addRows() 0 9 3
A finishCol() 0 25 4
A finishRow() 0 12 3
A ignore() 0 4 1
1
<?php
2
/**
3
 *
4
 * This file is part of Aura for PHP.
5
 *
6
 * @license http://opensource.org/licenses/mit-license.php MIT
7
 *
8
 */
9
namespace Aura\SqlQuery\Common;
10
11
use Aura\SqlQuery\AbstractDmlQuery;
12
use Aura\SqlQuery\Exception;
13
14
/**
15
 *
16
 * An object for INSERT queries.
17
 *
18
 * @package Aura.SqlQuery
19
 *
20
 */
21
class Insert extends AbstractDmlQuery implements InsertInterface
22
{
23
    /**
24
     *
25
     * The table to insert into (quoted).
26
     *
27
     * @var string
28
     *
29
     */
30
    protected $into;
31
32
    /**
33
     *
34
     * The table to insert into (raw, for last-insert-id use).
35
     *
36
     * @var string
37
     *
38
     */
39
    protected $into_raw;
40
41
    /**
42
     *
43
     * A map of fully-qualified `table.column` names to last-insert-id names.
44
     * This is used to look up the right last-insert-id name for a given table
45
     * and column. Generally useful only for extended tables in Postgres.
46
     *
47
     * @var array
48
     *
49
     */
50
    protected $last_insert_id_names;
51
52
    /**
53
     *
54
     * The current row-number we are adding column values for. This comes into
55
     * play only with bulk inserts.
56
     *
57
     * @var int
58
     *
59
     */
60
    protected $row = 0;
61
62
    /**
63
     *
64
     * A collection of `$col_values` for previous rows in bulk inserts.
65
     *
66
     * @var array
67
     *
68
     */
69
    protected $col_values_bulk = array();
70
71
    /**
72
     *
73
     * A collection of `$bind_values` for previous rows in bulk inserts.
74
     *
75
     * @var array
76
     *
77
     */
78
    protected $bind_values_bulk = array();
79
80
    /**
81
     *
82
     * The order in which columns will be bulk-inserted; this is taken from the
83
     * very first inserted row.
84
     *
85
     * @var array
86
     *
87
     */
88
    protected $col_order = array();
89
90
    /**
91
     *
92
     * Sets the map of fully-qualified `table.column` names to last-insert-id
93
     * names. Generally useful only for extended tables in Postgres.
94
     *
95
     * @param array $last_insert_id_names The list of ID names.
96
     *
97
     */
98 77
    public function setLastInsertIdNames(array $last_insert_id_names)
99
    {
100 77
        $this->last_insert_id_names = $last_insert_id_names;
101 77
    }
102
103
    /**
104
     *
105
     * Sets the table to insert into.
106
     *
107
     * @param string $into The table to insert into.
108
     *
109
     * @return $this
110
     *
111
     */
112 57
    public function into($into)
113
    {
114 57
        $this->into_raw = $into;
115 57
        $this->into = $this->quoter->quoteName($into);
116 57
        return $this;
117
    }
118
119
    /**
120
     *
121
     * Builds this query object into a string.
122
     *
123
     * @return string
124
     *
125
     */
126 42
    protected function build()
127
    {
128
        $stm = 'INSERT'
129 42
            . $this->builder->buildFlags($this->flags)
130 42
            . $this->builder->buildInto($this->into);
0 ignored issues
show
Bug introduced by
The method buildInto() does not exist on Aura\SqlQuery\Common\AbstractBuilder. It seems like you code against a sub-type of Aura\SqlQuery\Common\AbstractBuilder such as Aura\SqlQuery\Common\InsertBuilder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

130
            . $this->builder->/** @scrutinizer ignore-call */ buildInto($this->into);
Loading history...
131
132 42
        if ($this->row) {
133 20
            $this->finishRow();
134 20
            $stm .= $this->builder->buildValuesForBulkInsert($this->col_order, $this->col_values_bulk);
0 ignored issues
show
Bug introduced by
The method buildValuesForBulkInsert() does not exist on Aura\SqlQuery\Common\AbstractBuilder. It seems like you code against a sub-type of Aura\SqlQuery\Common\AbstractBuilder such as Aura\SqlQuery\Common\InsertBuilder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

134
            $stm .= $this->builder->/** @scrutinizer ignore-call */ buildValuesForBulkInsert($this->col_order, $this->col_values_bulk);
Loading history...
135
        } else {
136 22
            $stm .= $this->builder->buildValuesForInsert($this->col_values);
0 ignored issues
show
Bug introduced by
The method buildValuesForInsert() does not exist on Aura\SqlQuery\Common\AbstractBuilder. It seems like you code against a sub-type of Aura\SqlQuery\Common\AbstractBuilder such as Aura\SqlQuery\Common\InsertBuilder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

136
            $stm .= $this->builder->/** @scrutinizer ignore-call */ buildValuesForInsert($this->col_values);
Loading history...
137
        }
138
139 42
        return $stm;
140
    }
141
142
    /**
143
     *
144
     * Returns the proper name for passing to `PDO::lastInsertId()`.
145
     *
146
     * @param string $col The last insert ID column.
147
     *
148
     * @return mixed Normally null, since most drivers do not need a name;
149
     * alternatively, a string from `$last_insert_id_names`.
150
     *
151
     */
152 10
    public function getLastInsertIdName($col)
153
    {
154 10
        $key = $this->into_raw . '.' . $col;
155 10
        if (isset($this->last_insert_id_names[$key])) {
156 5
            return $this->last_insert_id_names[$key];
157
        }
158 5
    }
159
160
    /**
161
     *
162
     * Sets one column value placeholder; if an optional second parameter is
163
     * passed, that value is bound to the placeholder.
164
     *
165
     * @param string $col The column name.
166
     *
167
     * @param array $value Optional: a value to bind to the placeholder.
168
     *
169
     * @return $this
170
     *
171
     */
172 20
    public function col($col, ...$value)
173
    {
174 20
        return $this->addCol($col, ...$value);
175
    }
176
177
    /**
178
     *
179
     * Sets multiple column value placeholders. If an element is a key-value
180
     * pair, the key is treated as the column name and the value is bound to
181
     * that column.
182
     *
183
     * @param array $cols A list of column names, optionally as key-value
184
     * pairs where the key is a column name and the value is a bind value for
185
     * that column.
186
     *
187
     * @return $this
188
     *
189
     */
190 47
    public function cols(array $cols)
191
    {
192 47
        return $this->addCols($cols);
193
    }
194
195
    /**
196
     *
197
     * Sets a column value directly; the value will not be escaped, although
198
     * fully-qualified identifiers in the value will be quoted.
199
     *
200
     * @param string $col   The column name.
201
     *
202
     * @param string $value The column value expression.
203
     *
204
     * @return $this
205
     *
206
     */
207 32
    public function set($col, $value)
208
    {
209 32
        return $this->setCol($col, $value);
210
    }
211
212
    /**
213
     *
214
     * Gets the values to bind to placeholders.
215
     *
216
     * @return array
217
     *
218
     */
219 31
    public function getBindValues()
220
    {
221 31
        return array_merge(parent::getBindValues(), $this->bind_values_bulk);
222
    }
223
224
    /**
225
     *
226
     * Adds multiple rows for bulk insert.
227
     *
228
     * @param array $rows An array of rows, where each element is an array of
229
     * column key-value pairs. The values are bound to placeholders.
230
     *
231
     * @return $this
232
     *
233
     */
234 15
    public function addRows(array $rows)
235
    {
236 15
        foreach ($rows as $cols) {
237 15
            $this->addRow($cols);
238
        }
239 15
        if ($this->row > 1) {
240 10
            $this->finishRow();
241
        }
242 15
        return $this;
243
    }
244
245
    /**
246
     *
247
     * Add one row for bulk insert; increments the row counter and optionally
248
     * adds columns to the new row.
249
     *
250
     * When adding the first row, the counter is not incremented.
251
     *
252
     * After calling `addRow()`, you can further call `col()`, `cols()`, and
253
     * `set()` to work with the newly-added row. Calling `addRow()` again will
254
     * finish off the current row and start a new one.
255
     *
256
     * @param array $cols An array of column key-value pairs; the values are
257
     * bound to placeholders.
258
     *
259
     * @return $this
260
     *
261
     */
262 30
    public function addRow(array $cols = array())
263
    {
264 30
        if (empty($this->col_values)) {
265 15
            return $this->cols($cols);
266
        }
267
268 25
        if (empty($this->col_order)) {
269 25
            $this->col_order = array_keys($this->col_values);
270
        }
271
272 25
        $this->finishRow();
273 25
        $this->row ++;
274 25
        $this->cols($cols);
275 25
        return $this;
276
    }
277
278
    /**
279
     *
280
     * Adds IGNORE flag depending on DB syntax.
281
     *
282
     * @param bool $enable Set or unset flag (default true).
283
     * @throws Exception
284
     * @return \Aura\SqlQuery\Sqlite\Insert
285
     *
286 25
     */
287
    public function ignore($enable = true)
0 ignored issues
show
Unused Code introduced by
The parameter $enable is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

287
    public function ignore(/** @scrutinizer ignore-unused */ $enable = true)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
288 25
    {
289 15
        // override in child classes
290
        throw new Exception(get_class($this) . " doesn't support IGNORE flag");
291
    }
292 25
293 25
    /**
294
     *
295
     * Finishes off the current row in a bulk insert, collecting the bulk
296 25
     * values and resetting for the next row.
297 25
     *
298 25
     * @return null
299
     *
300
     */
301
    protected function finishRow()
302
    {
303
        if (empty($this->col_values)) {
304
            return;
305
        }
306
307
        foreach ($this->col_order as $col) {
308
            $this->finishCol($col);
309
        }
310
311 25
        $this->col_values = array();
312
        $this->bind_values = array();
313 25
    }
314 5
315
    /**
316
     *
317
     * Finishes off a single column of the current row in a bulk insert.
318 25
     *
319
     * @param string $col The column to finish off.
320
     *
321 25
     * @return null
322
     *
323 15
     * @throws Exception on named column missing from row.
324 15
     *
325
     */
326
    protected function finishCol($col)
327
    {
328 25
        if (! array_key_exists($col, $this->col_values)) {
329
            throw new Exception("Column $col missing from row {$this->row}.");
330
        }
331 25
332
        // get the current col_value
333
        $value = $this->col_values[$col];
334 25
335 25
        // is it *not* a placeholder?
336
        if (substr($value, 0, 1) != ':') {
337 25
            // copy the value as-is
338
            $this->col_values_bulk[$this->row][$col] = $value;
339
            return;
340
        }
341
342
        // retain col_values in bulk with the row number appended
343
        $this->col_values_bulk[$this->row][$col] = "{$value}_{$this->row}";
344
345
        // the existing placeholder name without : or row number
346
        $name = substr($value, 1);
347
348
        // retain bind_value in bulk with new placeholder
349
        if (array_key_exists($name, $this->bind_values)) {
350
            $this->bind_values_bulk["{$name}_{$this->row}"] = $this->bind_values[$name];
351
        }
352
    }
353
}
354