TYPO3 CMS  TYPO3_8-7
BulkInsertQuery.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
33 {
37  protected $columns;
38 
42  protected $connection;
43 
47  protected $table;
48 
52  protected $parameters = [];
53 
57  protected $types = [];
58 
62  protected $values = [];
63 
72  public function __construct(Connection $connection, string $table, array $columns = [])
73  {
74  $this->connection = $connection;
75  $this->table = $connection->quoteIdentifier($table);
76  $this->columns = $columns;
77  }
78 
84  public function __toString(): string
85  {
86  return $this->getSQL();
87  }
88 
112  public function addValues(array $values, array $types = [])
113  {
114  $valueSet = [];
115 
116  if (empty($this->columns)) {
117  foreach ($values as $index => $value) {
118  $this->parameters[] = $value;
119  $this->types[] = isset($types[$index]) ? $types[$index] : null;
120  $valueSet[] = '?';
121  }
122 
123  $this->values[] = $valueSet;
124 
125  return;
126  }
127 
128  foreach ($this->columns as $index => $column) {
129  $namedValue = isset($values[$column]) || array_key_exists($column, $values);
130  $positionalValue = isset($values[$index]) || array_key_exists($index, $values);
131 
132  if (!$namedValue && !$positionalValue) {
133  throw new \InvalidArgumentException(
134  sprintf('No value specified for column %s (index %d).', $column, $index),
135  1476049651
136  );
137  }
138 
139  if ($namedValue && $positionalValue && $values[$column] !== $values[$index]) {
140  throw new \InvalidArgumentException(
141  sprintf('Multiple values specified for column %s (index %d).', $column, $index),
142  1476049652
143  );
144  }
145 
146  $this->parameters[] = $namedValue ? $values[$column] : $values[$index];
147  $valueSet[] = '?';
148 
149  $namedType = isset($types[$column]);
150  $positionalType = isset($types[$index]);
151 
152  if ($namedType && $positionalType && $types[$column] !== $types[$index]) {
153  throw new \InvalidArgumentException(
154  sprintf('Multiple types specified for column %s (index %d).', $column, $index),
155  1476049653
156  );
157  }
158 
159  if ($namedType) {
160  $this->types[] = $types[$column];
161 
162  continue;
163  }
164 
165  if ($positionalType) {
166  $this->types[] = $types[$index];
167 
168  continue;
169  }
170 
171  $this->types[] = null;
172  }
173 
174  $this->values[] = $valueSet;
175  }
176 
185  public function execute(): int
186  {
187  $platform = $this->connection->getDatabasePlatform();
188  $insertMaxRows = $this->getInsertMaxRows();
189 
190  if ($insertMaxRows > 0 && count($this->values) > $insertMaxRows) {
191  throw new \LogicException(
192  sprintf(
193  'You can only insert %d rows in a single INSERT statement with platform "%s".',
194  $insertMaxRows,
195  $platform->getName()
196  ),
197  1476049654
198  );
199  }
200 
201  return $this->connection->executeUpdate($this->getSQL(), $this->parameters, $this->types);
202  }
203 
209  protected function getInsertMaxRows(): int
210  {
211  $platform = $this->connection->getDatabasePlatform();
212  if ($platform->getName() === 'mssql' && $platform->getReservedKeywordsList()->isKeyword('MERGE')) {
213  return 1000;
214  }
215 
216  return 0;
217  }
218 
224  public function getParameters(): array
225  {
226  return $this->parameters;
227  }
228 
234  public function getParameterTypes(): array
235  {
236  return $this->types;
237  }
238 
246  public function getSQL(): string
247  {
248  if (empty($this->values)) {
249  throw new \LogicException(
250  'You need to add at least one set of values before generating the SQL.',
251  1476049702
252  );
253  }
254 
256  $columnList = '';
257 
258  if (!empty($this->columns)) {
259  $columnList = sprintf(
260  ' (%s)',
261  implode(
262  ', ',
263  array_map(
264  function ($column) use ($connection) {
265  return $connection->quoteIdentifier($column);
266  },
268  )
269  )
270  );
271  }
272 
273  return sprintf(
274  'INSERT INTO %s%s VALUES (%s)',
275  $this->table,
276  $columnList,
277  implode(
278  '), (',
279  array_map(
280  function (array $valueSet) {
281  return implode(', ', $valueSet);
282  },
284  )
285  )
286  );
287  }
288 }
__construct(Connection $connection, string $table, array $columns=[])
addValues(array $values, array $types=[])