@@ -325,14 +325,8 @@ public function write($sessionId, $data)
325325
326326 try {
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
338332 return 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 ;
662661 switch (true ) {
663662 case '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 ;
666666 case '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 ;
671672 case '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 ;
677679 case '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 ;
679682 case '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
0 commit comments