@@ -325,14 +325,8 @@ public function write($sessionId, $data)
325325
326326try {
327327// We use a single MERGE SQL query when supported by the database.
328- $ mergeSql =$ this ->getMergeSql ();
329-
330- if (null !==$ mergeSql ) {
331- $ mergeStmt =$ this ->pdo ->prepare ($ mergeSql );
332- $ mergeStmt ->bindParam (':id ' ,$ sessionId , \PDO ::PARAM_STR );
333- $ mergeStmt ->bindParam (':data ' ,$ data , \PDO ::PARAM_LOB );
334- $ mergeStmt ->bindParam (':lifetime ' ,$ maxlifetime , \PDO ::PARAM_INT );
335- $ mergeStmt ->bindValue (':time ' ,time (), \PDO ::PARAM_INT );
328+ $ mergeStmt =$ this ->getMergeStatement ($ sessionId ,$ data ,$ maxlifetime );
329+ if (null !==$ mergeStmt ) {
336330$ mergeStmt ->execute ();
337331
338332return true ;
@@ -653,32 +647,65 @@ private function getSelectSql()
653647 }
654648
655649/**
656- * Returns a merge/upsert (i.e. insert or update)SQL query when supported by the database for writing session data.
650+ * Returns a merge/upsert (i.e. insert or update)statement when supported by the database for writing session data.
657651 *
658- * @return string|null The SQL string or null when not supported
652+ * @param string $sessionId Session ID
653+ * @param string $data Encoded session data
654+ * @param int $maxlifetime session.gc_maxlifetime
655+ *
656+ * @return \PDOStatement|null The merge statement or null when not supported
659657 */
660- private function getMergeSql ( )
658+ private function getMergeStatement ( $ sessionId , $ data , $ maxlifetime )
661659 {
660+ $ mergeSql =null ;
662661switch (true ) {
663662case 'mysql ' ===$ this ->driver :
664- return "INSERT INTO $ this ->table ( $ this ->idCol , $ this ->dataCol , $ this ->lifetimeCol , $ this ->timeCol ) VALUES (:id, :data, :lifetime, :time) " .
663+ $ mergeSql = "INSERT INTO $ this ->table ( $ this ->idCol , $ this ->dataCol , $ this ->lifetimeCol , $ this ->timeCol ) VALUES (:id, :data, :lifetime, :time) " .
665664"ON DUPLICATE KEY UPDATE $ this ->dataCol = VALUES( $ this ->dataCol ), $ this ->lifetimeCol = VALUES( $ this ->lifetimeCol ), $ this ->timeCol = VALUES( $ this ->timeCol ) " ;
665+ break ;
666666case 'oci ' ===$ this ->driver :
667667// DUAL is Oracle specific dummy table
668- return "MERGE INTO $ this ->table USING DUAL ON ( $ this ->idCol = :id) " .
669- "WHEN NOT MATCHED THEN INSERT ( $ this ->idCol , $ this ->dataCol , $ this ->lifetimeCol , $ this ->timeCol ) VALUES (:id, :data, :lifetime, :time) " .
670- "WHEN MATCHED THEN UPDATE SET $ this ->dataCol = :data, $ this ->lifetimeCol = :lifetime, $ this ->timeCol = :time " ;
668+ $ mergeSql ="MERGE INTO $ this ->table USING DUAL ON ( $ this ->idCol = ?) " .
669+ "WHEN NOT MATCHED THEN INSERT ( $ this ->idCol , $ this ->dataCol , $ this ->lifetimeCol , $ this ->timeCol ) VALUES (?, ?, ?, ?) " .
670+ "WHEN MATCHED THEN UPDATE SET $ this ->dataCol = ?, $ this ->lifetimeCol = ?, $ this ->timeCol = ? " ;
671+ break ;
671672case 'sqlsrv ' ===$ this ->driver &&version_compare ($ this ->pdo ->getAttribute (\PDO ::ATTR_SERVER_VERSION ),'10 ' ,'>= ' ):
672673// MERGE is only available since SQL Server 2008 and must be terminated by semicolon
673674// It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx
674- return "MERGE INTO $ this ->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ( $ this ->idCol = :id) " .
675- "WHEN NOT MATCHED THEN INSERT ( $ this ->idCol , $ this ->dataCol , $ this ->lifetimeCol , $ this ->timeCol ) VALUES (:id, :data, :lifetime, :time) " .
676- "WHEN MATCHED THEN UPDATE SET $ this ->dataCol = :data, $ this ->lifetimeCol = :lifetime, $ this ->timeCol = :time; " ;
675+ $ mergeSql ="MERGE INTO $ this ->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ( $ this ->idCol = ?) " .
676+ "WHEN NOT MATCHED THEN INSERT ( $ this ->idCol , $ this ->dataCol , $ this ->lifetimeCol , $ this ->timeCol ) VALUES (?, ?, ?, ?) " .
677+ "WHEN MATCHED THEN UPDATE SET $ this ->dataCol = ?, $ this ->lifetimeCol = ?, $ this ->timeCol = ?; " ;
678+ break ;
677679case 'sqlite ' ===$ this ->driver :
678- return "INSERT OR REPLACE INTO $ this ->table ( $ this ->idCol , $ this ->dataCol , $ this ->lifetimeCol , $ this ->timeCol ) VALUES (:id, :data, :lifetime, :time) " ;
680+ $ mergeSql ="INSERT OR REPLACE INTO $ this ->table ( $ this ->idCol , $ this ->dataCol , $ this ->lifetimeCol , $ this ->timeCol ) VALUES (:id, :data, :lifetime, :time) " ;
681+ break ;
679682case 'pgsql ' ===$ this ->driver &&version_compare ($ this ->pdo ->getAttribute (\PDO ::ATTR_SERVER_VERSION ),'9.5 ' ,'>= ' ):
680- return "INSERT INTO $ this ->table ( $ this ->idCol , $ this ->dataCol , $ this ->lifetimeCol , $ this ->timeCol ) VALUES (:id, :data, :lifetime, :time) " .
683+ $ mergeSql = "INSERT INTO $ this ->table ( $ this ->idCol , $ this ->dataCol , $ this ->lifetimeCol , $ this ->timeCol ) VALUES (:id, :data, :lifetime, :time) " .
681684"ON CONFLICT ( $ this ->idCol ) DO UPDATE SET ( $ this ->dataCol , $ this ->lifetimeCol , $ this ->timeCol ) = (EXCLUDED. $ this ->dataCol , EXCLUDED. $ this ->lifetimeCol , EXCLUDED. $ this ->timeCol ) " ;
685+ break ;
686+ }
687+
688+ if (null !==$ mergeSql ) {
689+ $ mergeStmt =$ this ->pdo ->prepare ($ mergeSql );
690+
691+ if ('sqlsrv ' ===$ this ->driver ||'oci ' ===$ this ->driver ) {
692+ $ mergeStmt ->bindParam (1 ,$ sessionId , \PDO ::PARAM_STR );
693+ $ mergeStmt ->bindParam (2 ,$ sessionId , \PDO ::PARAM_STR );
694+ $ mergeStmt ->bindParam (3 ,$ data , \PDO ::PARAM_LOB );
695+ $ mergeStmt ->bindParam (4 ,$ maxlifetime , \PDO ::PARAM_INT );
696+ $ mergeStmt ->bindValue (5 ,time (), \PDO ::PARAM_INT );
697+ $ mergeStmt ->bindParam (6 ,$ data , \PDO ::PARAM_LOB );
698+ $ mergeStmt ->bindParam (7 ,$ maxlifetime , \PDO ::PARAM_INT );
699+ $ mergeStmt ->bindValue (8 ,time (), \PDO ::PARAM_INT );
700+ }
701+ else {
702+ $ mergeStmt ->bindParam (':id ' ,$ sessionId , \PDO ::PARAM_STR );
703+ $ mergeStmt ->bindParam (':data ' ,$ data , \PDO ::PARAM_LOB );
704+ $ mergeStmt ->bindParam (':lifetime ' ,$ maxlifetime , \PDO ::PARAM_INT );
705+ $ mergeStmt ->bindValue (':time ' ,time (), \PDO ::PARAM_INT );
706+ }
707+
708+ return $ mergeStmt ;
682709 }
683710 }
684711