public function Insert::execute in Drupal 9
Same name in this branch
- 9 core/lib/Drupal/Core/Database/Query/Insert.php \Drupal\Core\Database\Query\Insert::execute()
- 9 core/lib/Drupal/Core/Database/Driver/sqlite/Insert.php \Drupal\Core\Database\Driver\sqlite\Insert::execute()
- 9 core/lib/Drupal/Core/Database/Driver/pgsql/Insert.php \Drupal\Core\Database\Driver\pgsql\Insert::execute()
- 9 core/lib/Drupal/Core/Database/Driver/mysql/Insert.php \Drupal\Core\Database\Driver\mysql\Insert::execute()
Same name and namespace in other branches
- 8 core/lib/Drupal/Core/Database/Driver/pgsql/Insert.php \Drupal\Core\Database\Driver\pgsql\Insert::execute()
Executes the insert query.
Return value
The last insert ID of the query, if one exists. If the query was given multiple sets of values to insert, the return value is undefined. If no fields are specified, this method will do nothing and return NULL. That That makes it safe to use in multi-insert loops.
Overrides Insert::execute
File
- core/
lib/ Drupal/ Core/ Database/ Driver/ pgsql/ Insert.php, line 21
Class
- Insert
- PostgreSQL implementation of \Drupal\Core\Database\Query\Insert.
Namespace
Drupal\Core\Database\Driver\pgsqlCode
public function execute() {
if (!$this
->preExecute()) {
return NULL;
}
$stmt = $this->connection
->prepareStatement((string) $this, $this->queryOptions);
// Fetch the list of blobs and sequences used on that table.
$table_information = $this->connection
->schema()
->queryTableInformation($this->table);
$max_placeholder = 0;
$blobs = [];
$blob_count = 0;
foreach ($this->insertValues as $insert_values) {
foreach ($this->insertFields as $idx => $field) {
if (isset($table_information->blob_fields[$field]) && $insert_values[$idx] !== NULL) {
$blobs[$blob_count] = fopen('php://memory', 'a');
fwrite($blobs[$blob_count], $insert_values[$idx]);
rewind($blobs[$blob_count]);
$stmt
->getClientStatement()
->bindParam(':db_insert_placeholder_' . $max_placeholder++, $blobs[$blob_count], \PDO::PARAM_LOB);
// Pre-increment is faster in PHP than increment.
++$blob_count;
}
else {
$stmt
->getClientStatement()
->bindParam(':db_insert_placeholder_' . $max_placeholder++, $insert_values[$idx]);
}
}
// Check if values for a serial field has been passed.
if (!empty($table_information->serial_fields)) {
foreach ($table_information->serial_fields as $index => $serial_field) {
$serial_key = array_search($serial_field, $this->insertFields);
if ($serial_key !== FALSE) {
$serial_value = $insert_values[$serial_key];
// Sequences must be greater than or equal to 1.
if ($serial_value === NULL || !$serial_value) {
$serial_value = 1;
}
// Set the sequence to the bigger value of either the passed
// value or the max value of the column. It can happen that another
// thread calls nextval() which could lead to a serial number being
// used twice. However, trying to insert a value into a serial
// column should only be done in very rare cases and is not thread
// safe by definition.
$this->connection
->query("SELECT setval('" . $table_information->sequences[$index] . "', GREATEST(MAX(" . $serial_field . "), :serial_value)) FROM {" . $this->table . "}", [
':serial_value' => (int) $serial_value,
]);
}
}
}
}
if (!empty($this->fromQuery)) {
// bindParam stores only a reference to the variable that is followed when
// the statement is executed. We pass $arguments[$key] instead of $value
// because the second argument to bindParam is passed by reference and
// the foreach statement assigns the element to the existing reference.
$arguments = $this->fromQuery
->getArguments();
foreach ($arguments as $key => $value) {
$stmt
->getClientStatement()
->bindParam($key, $arguments[$key]);
}
}
// Create a savepoint so we can rollback a failed query. This is so we can
// mimic MySQL and SQLite transactions which don't fail if a single query
// fails. This is important for tables that are created on demand. For
// example, \Drupal\Core\Cache\DatabaseBackend.
$this->connection
->addSavepoint();
try {
$stmt
->execute(NULL, $this->queryOptions);
if (isset($table_information->serial_fields[0])) {
$last_insert_id = $stmt
->fetchField();
}
$this->connection
->releaseSavepoint();
} catch (\PDOException $e) {
$this->connection
->rollbackSavepoint();
$message = $e
->getMessage() . ": " . $stmt
->getQueryString();
// Match all SQLSTATE 23xxx errors.
if (substr($e
->getCode(), -6, -3) == '23') {
throw new IntegrityConstraintViolationException($message, $e
->getCode(), $e);
}
else {
throw new DatabaseExceptionWrapper($message, 0, $e
->getCode());
}
} catch (\Exception $e) {
$this->connection
->rollbackSavepoint();
throw $e;
}
// Re-initialize the values array so that we can re-use this query.
$this->insertValues = [];
return $last_insert_id ?? NULL;
}