我在MySQL中有一个存储例程来执行SELECT
并调用另一个(即使不调用assert
子例程assert
也会出现同样的问题甚至使用SELECT null;
代替以下代码:
CREATE PROCEDURE `account_login`(IN `email` VARCHAR(50), IN `password` VARCHAR(200))
LANGUAGE SQL
NOT DETERMINISTIC
READS SQL DATA
SQL SECURITY INVOKER
COMMENT ''
BEGIN
SELECT SQL_CALC_FOUND_ROWS a.id AS id
FROM account AS a
WHERE a.email = email AND password_hash(password, a.password_salt) = a.password_hash
;
CALL assert((SELECT FOUND_ROWS()) = 1, 'WrongLoginCredentials', 'Bad login or bad password');
END$$
如果断言为assert
,则throw
调用另一个FALSE
例程。
CREATE PROCEDURE `assert`(
IN `assertion` BOOLEAN,
IN exceptionClass TINYTEXT,
IN errorMessage TEXT)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY INVOKER
COMMENT ''
BEGIN
IF NOT(`assertion`) THEN
CALL throw(exceptionClass, errorMessage);
END IF;
END$$
如果断言失败, throw
会调用SIGNAL 45000
。
CREATE PROCEDURE `throw`(
IN exceptionClass TINYTEXT,
IN errorMessage TEXT)
LANGUAGE SQL
NOT DETERMINISTIC
READS SQL DATA
SQL SECURITY INVOKER
COMMENT ''
BEGIN
ROLLBACK;
SELECT 1 AS exception, errorMessage as message, 42 AS code, exceptionClass as class;
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT=errorMessage,
MYSQL_ERRNO=42,
CLASS_ORIGIN=exceptionClass;
END$$
如果我使用假凭证在HeidiSQL中调用此过程,则会发出信号。如果我使用正确的凭据在HeidiSQL中调用它,它将返回结果集(SELECT
过程中的account_login
)。
但是当我使用PDO编写的语句在PHP中调用它时:
$this->pdo = new PDO($this->dbDsn, '...', '...', array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
));
$loginRequest = $this->pdo->prepare('CALL account_login(?, ?)');
$loginRequest->execute(array($email, $password));
$loginRequest->debugDumpParams();
do {
$resultSets[] = $loginRequest->fetchAll();
} while ($loginRequest->nextRowset());
$loginRequest->closeCursor();
然后我得到错误凭据的预期异常(因为SIGNAL
,罚款)和意外的GENERAL ERROR
,以获得第二次调用fetchAll
时提出的正确凭据。
同样的问题出现在throw
(没有SELECT
或没有SIGNAL
的情况下,或者在调用同一个PDO GENERAL ERROR
时没有任何结果account_login
具有正确的凭据)。
未准备好的陈述$this->pdo->query('CALL account_login($..., $...);
这在PHP 5.3中通过Apache发生,但也通过CLI在PHP 5.6中发生。
那里有什么问题?