Completed
Pull Request — 3.x (#173)
by
unknown
01:39
created

Insert::ignore()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 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 79
    public function setLastInsertIdNames(array $last_insert_id_names)
99
    {
100 79
        $this->last_insert_id_names = $last_insert_id_names;
101 79
    }
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 58
    public function into($into)
113
    {
114 58
        $this->into_raw = $into;
115 58
        $this->into = $this->quoter->quoteName($into);
116 58
        return $this;
117
    }
118
119
    /**
120
     *
121
     * Builds this query object into a string.
122
     *
123
     * @return string
124
     *
125
     */
126 43
    protected function build()
127
    {
128
        $stm = 'INSERT'
129 43
            . $this->builder->buildFlags($this->flags)
130 43
            . $this->builder->buildInto($this->into);
131
132 43
        if ($this->row) {
133 20
            $this->finishRow();
134 20
            $stm .= $this->builder->buildValuesForBulkInsert($this->col_order, $this->col_values_bulk);
135
        } else {
136 23
            $stm .= $this->builder->buildValuesForInsert($this->col_values);
137
        }
138
139 43
        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 48
    public function cols(array $cols)
191
    {
192 48
        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 33
    public function set($col, $value)
208
    {
209 33
        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
     */
287 1
    public function ignore($enable = true)
288
    {
289
        // override in child classes
290 1
        throw new Exception(get_class($this) . " doesn't support IGNORE flag");
291
    }
292
293
    /**
294
     *
295
     * Finishes off the current row in a bulk insert, collecting the bulk
296
     * values and resetting for the next row.
297
     *
298
     * @return null
299
     *
300
     */
301 25
    protected function finishRow()
302
    {
303 25
        if (empty($this->col_values)) {
304 15
            return;
305
        }
306
307 25
        foreach ($this->col_order as $col) {
308 25
            $this->finishCol($col);
309
        }
310
311 25
        $this->col_values = array();
312 25
        $this->bind_values = array();
313 25
    }
314
315
    /**
316
     *
317
     * Finishes off a single column of the current row in a bulk insert.
318
     *
319
     * @param string $col The column to finish off.
320
     *
321
     * @return null
322
     *
323
     * @throws Exception on named column missing from row.
324
     *
325
     */
326 25
    protected function finishCol($col)
327
    {
328 25
        if (! array_key_exists($col, $this->col_values)) {
329 5
            throw new Exception("Column $col missing from row {$this->row}.");
330
        }
331
332
        // get the current col_value
333 25
        $value = $this->col_values[$col];
334
335
        // is it *not* a placeholder?
336 25
        if (substr($value, 0, 1) != ':') {
337
            // copy the value as-is
338 15
            $this->col_values_bulk[$this->row][$col] = $value;
339 15
            return;
340
        }
341
342
        // retain col_values in bulk with the row number appended
343 25
        $this->col_values_bulk[$this->row][$col] = "{$value}_{$this->row}";
344
345
        // the existing placeholder name without : or row number
346 25
        $name = substr($value, 1);
347
348
        // retain bind_value in bulk with new placeholder
349 25
        if (array_key_exists($name, $this->bind_values)) {
350 25
            $this->bind_values_bulk["{$name}_{$this->row}"] = $this->bind_values[$name];
351
        }
352 25
    }
353
}
354