function Merge::executeNativeMerge
Executes the merge as a single native MERGE statement.
Parameters
object $table_information: The table information for the merge table, containing the blob fields.
Return value
int|null One of Merge::STATUS_INSERT, Merge::STATUS_UPDATE or NULL if the row already existed and no update was requested.
File
-
core/
modules/ pgsql/ src/ Driver/ Database/ pgsql/ Merge.php, line 93
Class
- Merge
- PostgreSQL implementation of \Drupal\Core\Database\Query\Merge.
Namespace
Drupal\pgsql\Driver\Database\pgsqlCode
protected function executeNativeMerge(object $table_information) : ?int {
$stmt = $this->connection
->prepareStatement((string) $this, $this->queryOptions, TRUE);
$client_statement = $stmt->getClientStatement();
$blobs = [];
$blob_count = 0;
$bind = function ($placeholder, $value, $field = NULL) use ($client_statement, $table_information, &$blobs, &$blob_count) {
if ($field !== NULL && isset($table_information->blob_fields[$field]) && $value !== NULL) {
$blobs[$blob_count] = fopen('php://memory', 'a');
fwrite($blobs[$blob_count], $value);
rewind($blobs[$blob_count]);
$client_statement->bindParam($placeholder, $blobs[$blob_count], \PDO::PARAM_LOB);
++$blob_count;
}
else {
$client_statement->bindValue($placeholder, $value);
}
};
// Arguments of the WHEN MATCHED THEN UPDATE clause. Expressions take
// priority over literal fields, matching the order in __toString().
if ($this->needsUpdate) {
foreach ($this->expressionFields as $data) {
if (!empty($data['arguments'])) {
foreach ($data['arguments'] as $placeholder => $argument) {
$bind($placeholder, $argument);
}
}
if ($data['expression'] instanceof SelectInterface) {
$data['expression']->compile($this->connection, $this);
foreach ($data['expression']->arguments() as $placeholder => $argument) {
$bind($placeholder, $argument);
}
}
}
$max_placeholder = 0;
foreach (array_diff_key($this->updateFields, $this->expressionFields) as $field => $value) {
$bind(':db_update_placeholder_' . $max_placeholder++, $value, $field);
}
}
// Arguments of the WHEN NOT MATCHED THEN INSERT clause.
$max_placeholder = 0;
foreach ($this->insertFields as $field => $value) {
$bind(':db_insert_placeholder_' . $max_placeholder++, $value, $field);
}
// Arguments of the ON condition.
$this->condition
->compile($this->connection, $this);
foreach ($this->condition
->arguments() as $placeholder => $value) {
$bind($placeholder, $value);
}
// 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.
if ($this->connection
->inTransaction()) {
$savepoint = $this->connection
->startTransaction('mimic_implicit_commit');
}
try {
$stmt->execute(NULL, $this->queryOptions);
if (isset($savepoint)) {
$savepoint->commitOrRelease();
}
} catch (\Exception $e) {
if (isset($savepoint)) {
$savepoint->rollback();
}
$this->connection
->exceptionHandler()
->handleExecutionException($e, $stmt, [], $this->queryOptions);
}
return match ($stmt->fetchField()) { 'INSERT' => self::STATUS_INSERT,
'UPDATE' => self::STATUS_UPDATE,
default => NULL,
};
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.