MySQL 注释导致 Perl DBI 的绑定参数计数混乱

发布于 2024-08-17 14:40:55 字数 1375 浏览 7 评论 0原文

我有以下 Perl 代码,它进行 DBI 调用:

my $artsql = q{ *** SNIP A BUNCH OF SQL ***
                where a.article_id != ?
                      and at.type_name != 'List Element'   -- don't get list children
                      and aw.flowstate = 'Published'
                      and a.visible_as_article = 1 }
      . ( $filter ? q{and ch.channel_id = ?
                      and cat.category_id = ? }
                  : '' ) 
         . q{order by a.publish_date desc
                limit 5};

my @bind = ( $article );
push @bind, ( $channel_id, $category_id ) if $filter;

my $articles = $dbh->selectall_arrayref( $artsql, { Slice => { } }, @bind );

$filter 打开时,此代码因错误而死亡:

DBD::mysql::db selectall_arrayref failed: called with 3 bind variables when 1 are needed

起初我认为这是中间三元条件的问题字符串的,(我已经被那个虫子咬过很多次了)但它是正确的。转储一些调试值表明查询和 @bind 数组已正确构造。

然后我注意到查询在 first 绑定变量之后有一个 SQL 注释,所以我一时兴起将其删除。噗,成功了!

根据 MySQL 评论文档

MySQL Server 支持三种注释样式: 从“#”字符到行尾。 从“--”序列到行尾。在 MySQL 中,“--”(双破折号)注释 >样式要求第二个破折号后面至少有一个空格或控件 字符(例如空格、制表符、换行符等)。

既然注释中有 -- 后跟一个空格并且(大概)以行尾结束,为什么 MySQL 会卡住呢? DBI 是否在幕后对换行符或空格做了一些奇怪的事情?

I've got the following Perl code which makes a DBI call:

my $artsql = q{ *** SNIP A BUNCH OF SQL ***
                where a.article_id != ?
                      and at.type_name != 'List Element'   -- don't get list children
                      and aw.flowstate = 'Published'
                      and a.visible_as_article = 1 }
      . ( $filter ? q{and ch.channel_id = ?
                      and cat.category_id = ? }
                  : '' ) 
         . q{order by a.publish_date desc
                limit 5};

my @bind = ( $article );
push @bind, ( $channel_id, $category_id ) if $filter;

my $articles = $dbh->selectall_arrayref( $artsql, { Slice => { } }, @bind );

When $filter is on, this code was dying with the error:

DBD::mysql::db selectall_arrayref failed: called with 3 bind variables when 1 are needed

At first I thought this was a problem with the ternary conditional in the middle of the string, (I've been bitten by that bug multiple times) but it was correct. Dumping some debug values shows that the query and @bind array were being constructed correctly.

I then noticed that the query had a SQL comment right after the first bind variable, so on a whim I removed it. Poof, it worked!

According to the MySQL docs on comments,

MySQL Server supports three comment styles:
From a “#” character to the end of the line.
From a “-- ” sequence to the end of the line. In MySQL, the “-- ” (double-dash) comment > style requires the second dash to be followed by at least one whitespace or control
character (such as a space, tab, newline, and so on).

Since the comment had -- followed by a space and (presumably) ended with the end of the line, why did MySQL choke? Is DBI doing something weird with newlines or whitespace behind the scenes?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦巷 2024-08-24 14:40:55

您的 SQL 或 Perl 代码看起来没有任何问题。

这可能是 DBI、DBD::mysql 或 MySQL 本身的错误。调试这个问题的第一步是找出哪个位有问题。因此,首先要消除变量。

首先消除绑定变量,对一些值进行硬编码,然后查看过程是否正确。如果不是,那么它可能是 DBD::mysql 或 DBI 中的错误。首先尝试更新两者,看看问题是否得到解决。如果这不起作用,请报告错误。请注意,存在类似的评论解析错误,因此很可能是 DBD ::mysql。 (您确定它是do not get listchildren而不是don't getlistchildren?)

接下来从等式中删除Perl。在 mysql shell 中运行查询(使用 \e 打开编辑器)。是否也有同样的问题呢?如果是这样,那么MySQL就有问题了。再次尝试升级。

There doesn't look to be anything wrong with your SQL or Perl code.

This could be a bug in DBI, DBD::mysql or MySQL itself. The first step in debugging this problem would be to find out which bit is at fault. So, start by eliminating the variables.

Start by eliminating the bind variables, hard code some values and see if the process correctly. If not then its probably a bug in DBD::mysql or DBI. First try updating both of them and see if the problem is fixed. If that doesn't work, report the bug. Note there's a similar comment parsing bug so it very may well be DBD::mysql. (You're sure it's do not get list children and not don't get list children?)

Next eliminate Perl from the equation. Run the query in the mysql shell (use \e to bring up an editor). Does it have the same problem? If so, then MySQL is at fault. Again, try upgrading.

一张白纸 2024-08-24 14:40:55

我在其他地方也看到过类似的事情发生。最有可能发生的情况是,在各个层中的某个地方(Schwern 是对的,你必须挖掘才能看到哪一层)的某些代码正在将换行符转换为空格,这在当时看来是一个合法的原因,并且所以你的评论占据了查询的整个其余部分。

我给人们的建议是不要在 SQL 中使用单行注释,除非使用命令行或其他专用客户端。涉及的层数太多,并且存在隐藏错误的机会。

I've seen similar things happen elsewhere. Most likely what happened is that somewhere in the various layers (Schwern is right that you'll have to dig to see which one) some piece of code is converting newlines to spaces for what must have seemed like a legitimate reason at the time, and so your comment is taking up the entire rest of the query.

The advice I give people is don't use single-line comments in SQL, unless using a command-line or other dedicated client. There's just too many layers involved and opportunity for hidden bugs.

比忠 2024-08-24 14:40:55

评论中的单引号搞砸了。
不知道这个错误的原因是什么。
将“不要获取最后一个孩子”更改为“不要获取最后一个孩子”,你的问题就会消失。

Single quotes inside the comment screws it up.
Don't know what is responsible for this bug.
Change "don't get last child" to "Do not get last child" and your problem will go away.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文