Completed
Pull Request — 3.x (#131)
by Paul
01:50
created

Insert::buildValuesForInsert()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.7462

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 3
cts 7
cp 0.4286
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 8
nc 2
nop 0
crap 2.7462
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
    protected $into_raw;
33
34
    /**
35
     *
36
     * A map of fully-qualified `table.column` names to last-insert-id names.
37
     * This is used to look up the right last-insert-id name for a given table
38
     * and column. Generally useful only for extended tables in Postgres.
39
     *
40
     * @var array
41
     *
42
     */
43
    protected $last_insert_id_names;
44
45
    /**
46
     *
47
     * The current row-number we are adding column values for. This comes into
48
     * play only with bulk inserts.
49
     *
50
     * @var int
51
     *
52
     */
53
    protected $row = 0;
54
55
    /**
56
     *
57
     * A collection of `$col_values` for previous rows in bulk inserts.
58
     *
59
     * @var array
60
     *
61
     */
62
    protected $col_values_bulk = array();
63
64
    /**
65
     *
66
     * A collection of `$bind_values` for previous rows in bulk inserts.
67
     *
68
     * @var array
69
     *
70
     */
71
    protected $bind_values_bulk = array();
72
73
    /**
74
     *
75
     * The order in which columns will be bulk-inserted; this is taken from the
76
     * very first inserted row.
77
     *
78
     * @var array
79
     *
80
     */
81
    protected $col_order = array();
82
83
    /**
84
     *
85
     * Sets the map of fully-qualified `table.column` names to last-insert-id
86
     * names. Generally useful only for extended tables in Postgres.
87
     *
88
     * @param array $last_insert_id_names The list of ID names.
89 77
     *
90
     */
91 77
    public function setLastInsertIdNames(array $last_insert_id_names)
92
    {
93
        $this->last_insert_id_names = $last_insert_id_names;
94
    }
95
96
    /**
97
     *
98
     * Sets the table to insert into.
99
     *
100
     * @param string $into The table to insert into.
101
     *
102
     * @return $this
103 57
     *
104
     */
105
    public function into($into)
106 57
    {
107 57
        $this->into_raw = $into;
108
        $this->into = $this->quoter->quoteName($into);
109
        return $this;
110
    }
111
112
    /**
113
     *
114
     * Builds this query object into a string.
115
     *
116
     * @return string
117 30
     *
118
     */
119 30
    protected function build()
120
    {
121
        $stm = 'INSERT'
122
            . $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...
123
            . $this->builder->buildInto($this->into);
124
125
        if ($this->row) {
126
            $this->finishRow();
127
            $stm .= $this->builder->buildValuesForBulkInsert($this->col_order, $this->col_values_bulk);
128
        } else {
129
            $stm .= $this->builder->buildValuesForInsert($this->col_values);
130
        }
131
132
        return $stm;
133
    }
134
135
    /**
136
     *
137
     * Returns the proper name for passing to `PDO::lastInsertId()`.
138
     *
139
     * @param string $col The last insert ID column.
140
     *
141
     * @return mixed Normally null, since most drivers do not need a name;
142
     * alternatively, a string from `$last_insert_id_names`.
143
     *
144
     */
145
    public function getLastInsertIdName($col)
146
    {
147
        $key = $this->into_raw . '.' . $col;
148 10
        if (isset($this->last_insert_id_names[$key])) {
149
            return $this->last_insert_id_names[$key];
150 10
        }
151 10
    }
152 5
153
    /**
154 5
     *
155
     * Sets one column value placeholder; if an optional second parameter is
156
     * passed, that value is bound to the placeholder.
157
     *
158
     * @param string $col The column name.
159
     *
160
     * @param array $value Optional: a value to bind to the placeholder.
161
     *
162
     * @return $this
163
     *
164
     */
165
    public function col($col, ...$value)
166
    {
167
        return $this->addCol($col, ...$value);
168
    }
169
170
    /**
171
     *
172
     * Sets multiple column value placeholders. If an element is a key-value
173
     * pair, the key is treated as the column name and the value is bound to
174
     * that column.
175
     *
176
     * @param array $cols A list of column names, optionally as key-value
177
     * pairs where the key is a column name and the value is a bind value for
178
     * that column.
179
     *
180
     * @return $this
181
     *
182
     */
183
    public function cols(array $cols)
184
    {
185
        return $this->addCols($cols);
186 17
    }
187
188
    /**
189 17
     *
190
     * Sets a column value directly; the value will not be escaped, although
191
     * fully-qualified identifiers in the value will be quoted.
192
     *
193
     * @param string $col   The column name.
194
     *
195
     * @param string $value The column value expression.
196
     *
197
     * @return $this
198
     *
199
     */
200
    public function set($col, $value)
201
    {
202
        return $this->setCol($col, $value);
203
    }
204
205
    /**
206
     *
207
     * Gets the values to bind to placeholders.
208
     *
209
     * @return array
210
     *
211
     */
212
    public function getBindValues()
213
    {
214
        return array_merge(parent::getBindValues(), $this->bind_values_bulk);
215
    }
216
217
    /**
218
     *
219
     * Adds multiple rows for bulk insert.
220
     *
221
     * @param array $rows An array of rows, where each element is an array of
222
     * column key-value pairs. The values are bound to placeholders.
223
     *
224
     * @return $this
225
     *
226
     */
227
    public function addRows(array $rows)
228
    {
229
        foreach ($rows as $cols) {
230 10
            $this->addRow($cols);
231
        }
232
        if ($this->row > 1) {
233
            $this->finishRow();
234
        }
235 10
        return $this;
236
    }
237
238 10
    /**
239 10
     *
240
     * Add one row for bulk insert; increments the row counter and optionally
241
     * adds columns to the new row.
242
     *
243
     * When adding the first row, the counter is not incremented.
244
     *
245
     * After calling `addRow()`, you can further call `col()`, `cols()`, and
246
     * `set()` to work with the newly-added row. Calling `addRow()` again will
247
     * finish off the current row and start a new one.
248
     *
249
     * @param array $cols An array of column key-value pairs; the values are
250
     * bound to placeholders.
251
     *
252
     * @return $this
253
     *
254
     */
255
    public function addRow(array $cols = array())
256
    {
257
        if (empty($this->col_values)) {
258 5
            return $this->cols($cols);
259
        }
260 5
261
        if (empty($this->col_order)) {
262
            $this->col_order = array_keys($this->col_values);
263
        }
264
265
        $this->finishRow();
266
        $this->row ++;
267
        $this->cols($cols);
268
        return $this;
269 5
    }
270
271 5
    /**
272 5
     *
273
     * Finishes off the current row in a bulk insert, collecting the bulk
274
     * values and resetting for the next row.
275
     *
276
     * @return null
277
     *
278
     */
279
    protected function finishRow()
280
    {
281
        if (empty($this->col_values)) {
282 15
            return;
283
        }
284
285 15
        foreach ($this->col_order as $col) {
286
            $this->finishCol($col);
287
        }
288
289
        $this->col_values = array();
290
        $this->bind_values = array();
291
    }
292 5
293 5
    /**
294
     *
295
     * Finishes off a single column of the current row in a bulk insert.
296
     *
297
     * @param string $col The column to finish off.
298
     *
299
     * @return null
300
     *
301
     * @throws Exception on named column missing from row.
302
     *
303
     */
304
    protected function finishCol($col)
305
    {
306
        if (! array_key_exists($col, $this->col_values)) {
307 5
            throw new Exception("Column $col missing from row {$this->row}.");
308
        }
309
310
        // get the current col_value
311
        $value = $this->col_values[$col];
312
313
        // is it *not* a placeholder?
314
        if (substr($value, 0, 1) != ':') {
315
            // copy the value as-is
316
            $this->col_values_bulk[$this->row][$col] = $value;
317
            return;
318
        }
319 5
320 5
        // retain col_values in bulk with the row number appended
321
        $this->col_values_bulk[$this->row][$col] = "{$value}_{$this->row}";
322
323
        // the existing placeholder name without : or row number
324
        $name = substr($value, 1);
325
326
        // retain bind_value in bulk with new placeholder
327
        if (array_key_exists($name, $this->bind_values)) {
328
            $this->bind_values_bulk["{$name}_{$this->row}"] = $this->bind_values[$name];
329
        }
330
    }
331
}
332