@@ -325,14 +325,8 @@ public function write($sessionId, $data)
325
325
326
326
try {
327
327
// 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 ) {
336
330
$ mergeStmt ->execute ();
337
331
338
332
return true ;
@@ -653,32 +647,65 @@ private function getSelectSql()
653
647
}
654
648
655
649
/**
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.
657
651
*
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
659
657
*/
660
- private function getMergeSql ( )
658
+ private function getMergeStatement ( $ sessionId , $ data , $ maxlifetime )
661
659
{
660
+ $ mergeSql = null ;
662
661
switch (true ) {
663
662
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) " .
665
664
"ON DUPLICATE KEY UPDATE $ this ->dataCol = VALUES( $ this ->dataCol ), $ this ->lifetimeCol = VALUES( $ this ->lifetimeCol ), $ this ->timeCol = VALUES( $ this ->timeCol ) " ;
665
+ break ;
666
666
case 'oci ' === $ this ->driver :
667
667
// 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 ;
671
672
case 'sqlsrv ' === $ this ->driver && version_compare ($ this ->pdo ->getAttribute (\PDO ::ATTR_SERVER_VERSION ), '10 ' , '>= ' ):
672
673
// MERGE is only available since SQL Server 2008 and must be terminated by semicolon
673
674
// 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 ;
677
679
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 ;
679
682
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) " .
681
684
"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 ;
682
709
}
683
710
}
684
711
0 commit comments