Completed
Push — 3.x-builder ( 47ec34 )
by Paul
02:38
created

Insert::buildValuesForBulkInsert()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 9
nc 2
nop 0
crap 2
1
<?php
2
/**
3
 *
4
 * This file is part of Aura for PHP.
5
 *
6
 * @license http://opensource.org/licenses/bsd-license.php BSD
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.
26
     *
27
     * @var string
28
     *
29
     */
30
    protected $into;
31
32
    /**
33
     *
34
     * A map of fully-qualified `table.column` names to last-insert-id names.
35
     * This is used to look up the right last-insert-id name for a given table
36
     * and column. Generally useful only for extended tables in Postgres.
37
     *
38
     * @var array
39
     *
40
     */
41
    protected $last_insert_id_names;
42
43
    /**
44
     *
45
     * The current row-number we are adding column values for. This comes into
46
     * play only with bulk inserts.
47
     *
48
     * @var int
49
     *
50
     */
51
    protected $row = 0;
52
53
    /**
54
     *
55
     * A collection of `$col_values` for previous rows in bulk inserts.
56
     *
57
     * @var array
58
     *
59
     */
60
    protected $col_values_bulk = array();
61
62
    /**
63
     *
64
     * A collection of `$bind_values` for previous rows in bulk inserts.
65
     *
66
     * @var array
67
     *
68
     */
69
    protected $bind_values_bulk = array();
70
71
    /**
72
     *
73
     * The order in which columns will be bulk-inserted; this is taken from the
74
     * very first inserted row.
75
     *
76
     * @var array
77
     *
78
     */
79
    protected $col_order = array();
80
81
    /**
82
     *
83
     * Sets the map of fully-qualified `table.column` names to last-insert-id
84
     * names. Generally useful only for extended tables in Postgres.
85
     *
86
     * @param array $last_insert_id_names The list of ID names.
87
     *
88
     */
89 77
    public function setLastInsertIdNames(array $last_insert_id_names)
90
    {
91 77
        $this->last_insert_id_names = $last_insert_id_names;
92 77
    }
93
94
    /**
95
     *
96
     * Sets the table to insert into.
97
     *
98
     * @param string $into The table to insert into.
99
     *
100
     * @return $this
101
     *
102
     */
103 57
    public function into($into)
104
    {
105
        // don't quote yet, we might need it for getLastInsertIdName()
106 57
        $this->into = $into;
107 57
        return $this;
108
    }
109
110
    /**
111
     *
112
     * Builds this query object into a string.
113
     *
114
     * @return string
115
     *
116
     */
117 30
    protected function build()
118
    {
119
        $stm = 'INSERT'
120 30
            . $this->builder->buildFlags($this->flags)
0 ignored issues
show
Bug introduced by
The property builder does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
121 30
            . $this->builder->buildInto($this->into);
122
123 30
        if ($this->row) {
124 16
            $this->finishRow();
125 16
            $stm .= $this->builder->buildValuesForBulkInsert($this->col_order, $this->col_values_bulk);
126 16
        } else {
127 14
            $stm .= $this->builder->buildValuesForInsert($this->col_values);
128
        }
129
130 30
        return $stm;
131
    }
132
133
    /**
134
     *
135
     * Returns the proper name for passing to `PDO::lastInsertId()`.
136
     *
137
     * @param string $col The last insert ID column.
138
     *
139
     * @return mixed Normally null, since most drivers do not need a name;
140
     * alternatively, a string from `$last_insert_id_names`.
141
     *
142
     */
143 10
    public function getLastInsertIdName($col)
144
    {
145 10
        $key = $this->into . '.' . $col;
146 10
        if (isset($this->last_insert_id_names[$key])) {
147 5
            return $this->last_insert_id_names[$key];
148
        }
149 5
    }
150
151
    /**
152
     *
153
     * Sets one column value placeholder; if an optional second parameter is
154
     * passed, that value is bound to the placeholder.
155
     *
156
     * @param string $col The column name.
157
     *
158
     * @param array $value Optional: a value to bind to the placeholder.
159
     *
160
     * @return $this
161
     *
162
     */
163 20
    public function col($col, ...$value)
164
    {
165 20
        return $this->addCol($col, ...$value);
166
    }
167
168
    /**
169
     *
170
     * Sets multiple column value placeholders. If an element is a key-value
171
     * pair, the key is treated as the column name and the value is bound to
172
     * that column.
173
     *
174
     * @param array $cols A list of column names, optionally as key-value
175
     * pairs where the key is a column name and the value is a bind value for
176
     * that column.
177
     *
178
     * @return $this
179
     *
180
     */
181 47
    public function cols(array $cols)
182
    {
183 47
        return $this->addCols($cols);
184
    }
185
186
    /**
187
     *
188
     * Sets a column value directly; the value will not be escaped, although
189
     * fully-qualified identifiers in the value will be quoted.
190
     *
191
     * @param string $col   The column name.
192
     *
193
     * @param string $value The column value expression.
194
     *
195
     * @return $this
196
     *
197
     */
198 32
    public function set($col, $value)
199
    {
200 32
        return $this->setCol($col, $value);
201
    }
202
203
    /**
204
     *
205
     * Gets the values to bind to placeholders.
206
     *
207
     * @return array
208
     *
209
     */
210 31
    public function getBindValues()
211
    {
212 31
        return array_merge(parent::getBindValues(), $this->bind_values_bulk);
213
    }
214
215
    /**
216
     *
217
     * Adds multiple rows for bulk insert.
218
     *
219
     * @param array $rows An array of rows, where each element is an array of
220
     * column key-value pairs. The values are bound to placeholders.
221
     *
222
     * @return $this
223
     *
224
     */
225 15
    public function addRows(array $rows)
226
    {
227 15
        foreach ($rows as $cols) {
228 15
            $this->addRow($cols);
229 15
        }
230 15
        if ($this->row > 1) {
231 10
            $this->finishRow();
232 10
        }
233 15
        return $this;
234
    }
235
236
    /**
237
     *
238
     * Add one row for bulk insert; increments the row counter and optionally
239
     * adds columns to the new row.
240
     *
241
     * When adding the first row, the counter is not incremented.
242
     *
243
     * After calling `addRow()`, you can further call `col()`, `cols()`, and
244
     * `set()` to work with the newly-added row. Calling `addRow()` again will
245
     * finish off the current row and start a new one.
246
     *
247
     * @param array $cols An array of column key-value pairs; the values are
248
     * bound to placeholders.
249
     *
250
     * @return $this
251
     *
252
     */
253 30
    public function addRow(array $cols = array())
254
    {
255 30
        if (empty($this->col_values)) {
256 15
            return $this->cols($cols);
257
        }
258
259 25
        if (empty($this->col_order)) {
260 25
            $this->col_order = array_keys($this->col_values);
261 25
        }
262
263 25
        $this->finishRow();
264 25
        $this->row ++;
265 25
        $this->cols($cols);
266 25
        return $this;
267
    }
268
269
    /**
270
     *
271
     * Finishes off the current row in a bulk insert, collecting the bulk
272
     * values and resetting for the next row.
273
     *
274
     * @return null
275
     *
276
     */
277 25
    protected function finishRow()
278
    {
279 25
        if (empty($this->col_values)) {
280 15
            return;
281
        }
282
283 25
        foreach ($this->col_order as $col) {
284 25
            $this->finishCol($col);
285 25
        }
286
287 25
        $this->col_values = array();
288 25
        $this->bind_values = array();
289 25
    }
290
291
    /**
292
     *
293
     * Finishes off a single column of the current row in a bulk insert.
294
     *
295
     * @param string $col The column to finish off.
296
     *
297
     * @return null
298
     *
299
     * @throws Exception on named column missing from row.
300
     *
301
     */
302 25
    protected function finishCol($col)
303
    {
304 25
        if (! array_key_exists($col, $this->col_values)) {
305 5
            throw new Exception("Column $col missing from row {$this->row}.");
306
        }
307
308
        // get the current col_value
309 25
        $value = $this->col_values[$col];
310
311
        // is it *not* a placeholder?
312 25
        if (substr($value, 0, 1) != ':') {
313
            // copy the value as-is
314 15
            $this->col_values_bulk[$this->row][$col] = $value;
315 15
            return;
316
        }
317
318
        // retain col_values in bulk with the row number appended
319 25
        $this->col_values_bulk[$this->row][$col] = "{$value}_{$this->row}";
320
321
        // the existing placeholder name without : or row number
322 25
        $name = substr($value, 1);
323
324
        // retain bind_value in bulk with new placeholder
325 25
        if (array_key_exists($name, $this->bind_values)) {
326 25
            $this->bind_values_bulk["{$name}_{$this->row}"] = $this->bind_values[$name];
327 25
        }
328 25
    }
329
}
330