Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. PdoSessionHandler.php

function PdoSessionHandler::getMergeStatement

Returns a merge/upsert (i.e. insert or update) statement when supported by the database for writing session data.

1 call to PdoSessionHandler::getMergeStatement()
PdoSessionHandler::doWrite in vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php

File

vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php, line 841

Class

PdoSessionHandler
Session handler using a PDO connection to read and write data.

Namespace

Symfony\Component\HttpFoundation\Session\Storage\Handler

Code

private function getMergeStatement(string $sessionId, string $data, int $maxlifetime) : ?\PDOStatement {
    switch (true) {
        case 'mysql' === $this->driver:
            $mergeSql = "INSERT INTO {$this->table} ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (:id, :data, :expiry, :time) " . "ON DUPLICATE KEY UPDATE {$this->dataCol} = VALUES({$this->dataCol}), {$this->lifetimeCol} = VALUES({$this->lifetimeCol}), {$this->timeCol} = VALUES({$this->timeCol})";
            break;
        case 'sqlsrv' === $this->driver && version_compare($this->pdo
            ->getAttribute(\PDO::ATTR_SERVER_VERSION), '10', '>='):
            // MERGE is only available since SQL Server 2008 and must be terminated by semicolon
            // It also requires HOLDLOCK according to https://weblogs.sqlteam.com/dang/2009/01/31/upsert-race-condition-with-merge/
            $mergeSql = "MERGE INTO {$this->table} WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ({$this->idCol} = ?) " . "WHEN NOT MATCHED THEN INSERT ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (?, ?, ?, ?) " . "WHEN MATCHED THEN UPDATE SET {$this->dataCol} = ?, {$this->lifetimeCol} = ?, {$this->timeCol} = ?;";
            break;
        case 'sqlite' === $this->driver:
            $mergeSql = "INSERT OR REPLACE INTO {$this->table} ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (:id, :data, :expiry, :time)";
            break;
        case 'pgsql' === $this->driver && version_compare($this->pdo
            ->getAttribute(\PDO::ATTR_SERVER_VERSION), '9.5', '>='):
            $mergeSql = "INSERT INTO {$this->table} ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (:id, :data, :expiry, :time) " . "ON CONFLICT ({$this->idCol}) DO UPDATE SET ({$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) = (EXCLUDED.{$this->dataCol}, EXCLUDED.{$this->lifetimeCol}, EXCLUDED.{$this->timeCol})";
            break;
        default:
            // MERGE is not supported with LOBs: https://oracle.com/technetwork/articles/fuecks-lobs-095315.html
            return null;
    }
    $mergeStmt = $this->pdo
        ->prepare($mergeSql);
    if ('sqlsrv' === $this->driver) {
        $mergeStmt->bindParam(1, $sessionId, \PDO::PARAM_STR);
        $mergeStmt->bindParam(2, $sessionId, \PDO::PARAM_STR);
        $mergeStmt->bindParam(3, $data, \PDO::PARAM_LOB);
        $mergeStmt->bindValue(4, time() + $maxlifetime, \PDO::PARAM_INT);
        $mergeStmt->bindValue(5, time(), \PDO::PARAM_INT);
        $mergeStmt->bindParam(6, $data, \PDO::PARAM_LOB);
        $mergeStmt->bindValue(7, time() + $maxlifetime, \PDO::PARAM_INT);
        $mergeStmt->bindValue(8, time(), \PDO::PARAM_INT);
    }
    else {
        $mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
        $mergeStmt->bindParam(':data', $data, \PDO::PARAM_LOB);
        $mergeStmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT);
        $mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT);
    }
    return $mergeStmt;
}

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal