@@ -580,11 +580,11 @@ private function doAdvisoryLock($sessionId)
580
580
return $ releaseStmt ;
581
581
case 'pgsql ' :
582
582
// Obtaining an exclusive session level advisory lock requires an integer key.
583
- // So we convert the HEX representation of the session id to an integer .
584
- // Since integers are signed, we have to skip one hex char to fit in the range .
585
- if (4 === PHP_INT_SIZE ) {
586
- $ sessionInt1 = hexdec ( substr ( $ sessionId, 0 , 7 ) );
587
- $ sessionInt2 = hexdec (substr ($ sessionId , 7 , 7 ));
583
+ // When session.sid_bits_per_character > 4, the session id can contain non-hex-characters .
584
+ // So we cannot just use hexdec() .
585
+ if (4 === \ PHP_INT_SIZE ) {
586
+ $ sessionInt1 = $ this -> convertStringToInt ( $ sessionId );
587
+ $ sessionInt2 = $ this -> convertStringToInt (substr ($ sessionId , 4 , 4 ));
588
588
589
589
$ stmt = $ this ->pdo ->prepare ('SELECT pg_advisory_lock(:key1, :key2) ' );
590
590
$ stmt ->bindValue (':key1 ' , $ sessionInt1 , \PDO ::PARAM_INT );
@@ -595,7 +595,7 @@ private function doAdvisoryLock($sessionId)
595
595
$ releaseStmt ->bindValue (':key1 ' , $ sessionInt1 , \PDO ::PARAM_INT );
596
596
$ releaseStmt ->bindValue (':key2 ' , $ sessionInt2 , \PDO ::PARAM_INT );
597
597
} else {
598
- $ sessionBigInt = hexdec ( substr ( $ sessionId, 0 , 15 ) );
598
+ $ sessionBigInt = $ this -> convertStringToInt ( $ sessionId );
599
599
600
600
$ stmt = $ this ->pdo ->prepare ('SELECT pg_advisory_lock(:key) ' );
601
601
$ stmt ->bindValue (':key ' , $ sessionBigInt , \PDO ::PARAM_INT );
@@ -613,6 +613,27 @@ private function doAdvisoryLock($sessionId)
613
613
}
614
614
}
615
615
616
+ /**
617
+ * Encodes the first 4 (when PHP_INT_SIZE == 4) or 8 characters of the string as an integer.
618
+ *
619
+ * Keep in mind, PHP integers are signed.
620
+ *
621
+ * @param string $string
622
+ *
623
+ * @return int
624
+ */
625
+ private function convertStringToInt ($ string )
626
+ {
627
+ if (4 === \PHP_INT_SIZE ) {
628
+ return (ord ($ string [3 ]) << 24 ) + (ord ($ string [2 ]) << 16 ) + (ord ($ string [1 ]) << 8 ) + ord ($ string [0 ]);
629
+ }
630
+
631
+ $ int1 = (ord ($ string [7 ]) << 24 ) + (ord ($ string [6 ]) << 16 ) + (ord ($ string [5 ]) << 8 ) + ord ($ string [4 ]);
632
+ $ int2 = (ord ($ string [3 ]) << 24 ) + (ord ($ string [2 ]) << 16 ) + (ord ($ string [1 ]) << 8 ) + ord ($ string [0 ]);
633
+
634
+ return $ int2 + ($ int1 << 32 );
635
+ }
636
+
616
637
/**
617
638
* Return a locking or nonlocking SQL query to read session information.
618
639
*
0 commit comments