Completed
Push — 3.x ( e5eb1c...76cecd )
by Paul
9s
created

Insert::addRow()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 15
ccs 9
cts 9
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 9
nc 3
nop 1
crap 3
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
     *
90
     */
91 77
    public function setLastInsertIdNames(array $last_insert_id_names)
92
    {
93 77
        $this->last_insert_id_names = $last_insert_id_names;
94 77
    }
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
     *
104
     */
105 57
    public function into($into)
106
    {
107 57
        $this->into_raw = $into;
108 57
        $this->into = $this->quoter->quoteName($into);
109 57
        return $this;
110
    }
111
112
    /**
113
     *
114
     * Builds this query object into a string.
115
     *
116
     * @return string
117
     *
118
     */
119 42
    protected function build()
120
    {
121
        $stm = 'INSERT'
122 42
            . $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 42
            . $this->builder->buildInto($this->into);
124
125 42
        if ($this->row) {
126 20
            $this->finishRow();
127 20
            $stm .= $this->builder->buildValuesForBulkInsert($this->col_order, $this->col_values_bulk);
128
        } else {
129 22
            $stm .= $this->builder->buildValuesForInsert($this->col_values);
130
        }
131
132 42
        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 10
    public function getLastInsertIdName($col)
146
    {
147 10
        $key = $this->into_raw . '.' . $col;
148 10
        if (isset($this->last_insert_id_names[$key])) {
149 5
            return $this->last_insert_id_names[$key];
150
        }
151 5
    }
152
153
    /**
154
     *
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 20
    public function col($col, ...$value)
166
    {
167 20
        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 47
    public function cols(array $cols)
184
    {
185 47
        return $this->addCols($cols);
186
    }
187
188
    /**
189
     *
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 32
    public function set($col, $value)
201
    {
202 32
        return $this->setCol($col, $value);
203
    }
204
205
    /**
206
     *
207
     * Gets the values to bind to placeholders.
208
     *
209
     * @return array
210
     *
211
     */
212 31
    public function getBindValues()
213
    {
214 31
        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 15
    public function addRows(array $rows)
228
    {
229 15
        foreach ($rows as $cols) {
230 15
            $this->addRow($cols);
231
        }
232 15
        if ($this->row > 1) {
233 10
            $this->finishRow();
234
        }
235 15
        return $this;
236
    }
237
238
    /**
239
     *
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 30
    public function addRow(array $cols = array())
256
    {
257 30
        if (empty($this->col_values)) {
258 15
            return $this->cols($cols);
259
        }
260
261 25
        if (empty($this->col_order)) {
262 25
            $this->col_order = array_keys($this->col_values);
263
        }
264
265 25
        $this->finishRow();
266 25
        $this->row ++;
267 25
        $this->cols($cols);
268 25
        return $this;
269
    }
270
271
    /**
272
     *
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 25
    protected function finishRow()
280
    {
281 25
        if (empty($this->col_values)) {
282 15
            return;
283
        }
284
285 25
        foreach ($this->col_order as $col) {
286 25
            $this->finishCol($col);
287
        }
288
289 25
        $this->col_values = array();
290 25
        $this->bind_values = array();
291 25
    }
292
293
    /**
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 25
    protected function finishCol($col)
305
    {
306 25
        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 25
        $value = $this->col_values[$col];
312
313
        // is it *not* a placeholder?
314 25
        if (substr($value, 0, 1) != ':') {
315
            // copy the value as-is
316 15
            $this->col_values_bulk[$this->row][$col] = $value;
317 15
            return;
318
        }
319
320
        // retain col_values in bulk with the row number appended
321 25
        $this->col_values_bulk[$this->row][$col] = "{$value}_{$this->row}";
322
323
        // the existing placeholder name without : or row number
324 25
        $name = substr($value, 1);
325
326
        // retain bind_value in bulk with new placeholder
327 25
        if (array_key_exists($name, $this->bind_values)) {
328 25
            $this->bind_values_bulk["{$name}_{$this->row}"] = $this->bind_values[$name];
329
        }
330 25
    }
331
}
332