MySQL 无法使用准备好的语句选择使用自定义函数的视图(权限错误),但直接查询有效

MySQL view using self-defined function cannot be selected (privileges error) with prepared statement but direct query works

在为私人项目构建一个现在稍微复杂的数据库时,我们发现了一个问题,这也可能是一个错误,但我想在这里寻求一些建议,因为也许我的假设是错误的。

序言: 所有视图和功能都创建为 DEFINER = `root`@`localhost` SQL SECURITY DEFINER。建立连接的最终用户仅限于他可以使用的内容。 对于 FUNCTION(这可能是 MySQL Workbench 行为),SQL SECURITY DEFINER 永远不会被转录到 DDL(?),但是查看 SELECT SECURITY_TYPE FROM information_schema.routines,肯定是这样写的定义器。

主要问题: 所以当我尝试在 VIEW 的列上使用 FUNCTION 时,问题就出现了,其中 FUNCTION 使用 VIEW 本身,而用户只有 SELECT PRIVILEGES 在第一个提到的 VIEW 上。 如果我直接执行 SELECT,一切都按预期工作,但如果我将 SELECT 放在 PREPAREd 语句中并执行它,我会收到 Error Code: 1356. View 'test.usableview' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them 错误。 MySQL 目前使用的服务器是 8.0.22 Windows 10,v8.0.27(最新版本)有同样的问题。 最小示例:

CREATE SCHEMA `test`;
USE `test`;
CREATE TABLE IF NOT EXISTS `test`.`basetable_noRights` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `something` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB;
INSERT INTO `test`.`basetable_noRights` VALUES (1, 'test');
CREATE TABLE IF NOT EXISTS `test`.`basetable_noRights2` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `something` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB;
INSERT INTO `test`.`basetable_noRights2` VALUES (1, 'finally not visible');
CREATE  OR REPLACE VIEW  `test`.`firstlevelview` AS
SELECT 1 AS id, CONCAT(something, ' 1') AS foo FROM `test`.`basetable_noRights`;
DELIMITER $$
CREATE FUNCTION `user_has_no_rights_function`(i INT) RETURNS VARCHAR(99) CHARSET utf8
    READS SQL DATA
begin
    SELECT foo INTO @var FROM `test`.`firstlevelview` WHERE id = 1;
    return @var;
end$$
DELIMITER ;
CREATE  OR REPLACE VIEW  `test`.`usableview` AS
SELECT user_has_no_rights_function(id) AS final FROM`test`.`basetable_noRights2` WHERE id = 1;
CREATE  OR REPLACE VIEW  `test`.`view_without_function` AS
SELECT snd.foo, fst.something FROM `test`.`firstlevelview` snd, `test`.`basetable_noRights` fst;
CREATE USER 'foo'@'%' IDENTIFIED BY 'bar';
GRANT SELECT ON TABLE `test`.`usableview` TO 'foo'@'%';
GRANT SELECT ON TABLE `test`.`view_without_function` TO 'foo'@'%';
FLUSH PRIVILEGES;
SELECT * FROM view_without_function;        -- works
PREPARE asdf FROM "SELECT * FROM view_without_function";
EXECUTE asdf;                   -- works
SELECT * FROM usableview;           -- works
PREPARE asdf2 FROM "SELECT * FROM usableview";
EXECUTE asdf2;                  -- does not work

顺便说一句,当将函数从 TABLE 而不是 VIEW 更改为 SELECT 时,一切都再次按预期运行。 也许这都是设计使然,但在那种情况下我不理解设计。也许实际上对于准备好的语句需要授予更多权限,我们很幸运直到这里一切正常。

也许这只是一些我不知道的服务器端设置?

我特别期待所有“您需要为基础表授予权限”,尽管我们已经在上面的示例中看到这不是(完全)正确的,因为直接 SELECT 有效并且 MySQL 文档还指出(在我们的例子中)使用了根定义者的特权;)

所描述的行为现在是一个已确认的错误,请参阅https://bugs.mysql.com/bug.php?id=105807