我正在尝试做一个简单的查询作为准备好的声明,但没有成功.这是代码:
package sqltest;
use DBI;

DBI->trace(2);

my $dbh = DBI->connect('dbi:MysqL:database=test;host=***;port=3306','the_username','****');
my $prep = 'SELECT me.id,me.session_data,me.expires FROM sys_session me WHERE me.id = ?';
$dbh->{raiseerror} = 1;
my $sth = $dbh->prepare($prep);
$sth->bind_param(1,'session:06b6d2138df949524092eefc066ee5ab3598bf96');
$sth->execute;
DBI::dump_results($sth);

MysqL服务器响应”’附近的语法错误.

DBI跟踪的输出显示

-> bind_param for DBD::MysqL::st (DBI::st=HASH(0x21e35cc)~0x21e34f4 1 'session:06b6d2138df949524092eefc066ee5ab3598bf96') thr#3ccdb4
 Called: dbd_bind_ph
  <- bind_param= ( 1 ) [1 items] at perl_test_dbi_params.pl line 10
[...]
>parse_params statement SELECT me.id,me.expires FROM sys_session me WHERE me.id = ?
Binding parameters: SELECT me.id,me.expires FROM sys_session me WHERE me.id = '
[...]
DBD::MysqL::st execute Failed: You have an error in your sql Syntax; check the manual that corresponds to your MysqL server version for the right Syntax to use near ''' at line 1

所以对我而言,看起来声明并没有得到应有的准备.
当我发送没有参数的查询时,它按预期工作.

我在这里想念什么?

DBI版本是DBI 1.637-ithread,MysqL版本是5.5.57-0 deb8u1

使用针对MSWin32-x86-multi-thread-64int构建的Windows perl 5,版本26,subversion 1(v5.26.1)进行测试
和Ubuntu perl 5,版本22,颠覆1(v5.22.1)为x86_64-linux-gnu-thread-multi构建

EDIT1:
for context:我在使用Catalyst和Catalyst::Plugin::Session::Store::DBIC时注意到了这个问题.这里,id-column是一个Varchar(72)类型,它包含一个session-id.

EDIT2:

> DBD :: MysqL版本是4.043
>通过$sth->执行绑定(‘session:foo’);导致同样的问题
>通过$sth-> bind_param绑定(‘session:foo’,sql_VARCHAR);导致同样的问题
>绑定数字字段确实有效,但只能使用显式类型定义$sth-> bind_param(1,1512407082,sql_INTEGER);

EDIT3:
我找到了做更多测试的时间,但没有令人满意的结果:

>我能够使用较旧的服务器进行测试并且有效. DBI和DBD :: MysqL的版本是相同的,但我发现服务器使用的是MysqL 5.5客户端,在DBI-trace中报告为MysqL_VERSION_ID 50557,而我的两个原始测试服务器都使用MysqL 5.7 MysqL_VERSION_ID 50720和MysqL_VERSION_ID 50716
>使用$dbh-> {MysqL_server_prepare} = 1;它有效!也许这有助于找到这个问题的人,但我现在更愿意找到问题的真正原因

解决方法

从您的跟踪日志可以看出,问号占位符(?)被DBD :: MysqL替换为一个撇号(‘).所以它是纯DBD :: MysqL的bug.乍一看它完全没有意义……因为占位符被放入两个撇号的参数替换.

可以在那里找到执行此占位符替换的相关代码:https://metacpan.org/source/MICHIELB/DBD-mysql-4.043/dbdimp.c#L784-786

*ptr++ = '\'';
          ptr += MysqL_real_escape_string(sock,ptr,valbuf,vallen);
          *ptr++ = '\'';

所以问题是,上面的C代码可以在* ptr缓冲区中产生一个撇号吗?答案是肯定的,当MysqL_real_escape_string()返回相同值的整数作为指针大小减去1 – 当两个撇号被写入* ptr缓冲区中的相同位置时,模拟递减1的数值运算.

这会发生吗?是的,它可以,因为Oracle在MysqL 5.7.6客户端库中更改了MysqL_real_escape_string()C函数的API:

https://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-6.html#mysqld-5-7-6-feature

Incompatible Change: A new C API function,MysqL_real_escape_string_quote(),has been implemented as a replacement for MysqL_real_escape_string() because the latter function can fail to properly encode characters when the NO_BACKSLASH_ESCAPES sql mode is enabled. In this case,MysqL_real_escape_string() cannot escape quote characters except by doubling them,and to do this properly,it must kNow more information about the quoting context than is available. MysqL_real_escape_string_quote() takes an extra argument for specifying the quoting context. For usage details,see MysqL_real_escape_string_quote().

MysqL 5.7.6版本的MysqL_real_escape_string()文档说:

https://dev.mysql.com/doc/refman/5.7/en/mysql-real-escape-string.html

Return Values: The length of the encoded string that is placed into the to argument,not including the terminating null byte,or -1 if an error occurs.

因此,如果在MysqL服务器上启用NO_BACKSLASH_ESCAPES sql模式,则MysqL 5.7.6客户端的MysqL_real_escape_string()无法正常工作并返回错误,因此-1会转换为unsigned long. unsigned long在32bit和64bit x86平台上都与指针大小相同,因此在DBD :: MysqL驱动程序的C代码之上产生一个撇号字符.

现在我在下面的pull请求中修复了DBD::MariaDB驱动程序(DBD :: MysqL的fork)的这个问题:https://github.com/gooddata/DBD-MariaDB/pull/77

所以当使用MysqL 5.7客户端库编译时,DBD :: MariaDB也是兼容的.

Perl DBI(MySQL)在预准备语句中放置单引号而不是实际参数的更多相关文章

  1. HTML5 Web缓存和运用程序缓存(cookie,session)

    这篇文章主要介绍了HTML5 Web缓存和运用程序缓存(cookie,session),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. HTML5 WebSocket实现点对点聊天的示例代码

    这篇文章主要介绍了HTML5 WebSocket实现点对点聊天的示例代码的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. ios – 在Swift的UIView中找到UILabel

    我正在尝试在我的UIViewControllers的超级视图中找到我的UILabels.这是我的代码:这是在Objective-C中推荐的方式,但是在Swift中我只得到UIViews和CALayer.我肯定在提供给这个方法的视图中有UILabel.我错过了什么?我的UIViewController中的调用:解决方法使用函数式编程概念可以更轻松地实现这一目标.

  4. iOS Swift上弃用后Twitter.sharedInstance().session()?. userName的替代方案

    解决方法如果您仍在寻找解决方案,请参阅以下内容:

  5. 使用Fabric SDK iOS访问Twitter用户时间线

    我试图在这个问题上挣扎两天.我正在使用FabricSDK和Rest工具包,试图为Twitter使用不同的RestAPIWeb服务.我可以使用具有authTokenSecret,authToken和其他值的会话对象的TWTRLogInButton成功登录.当我尝试获取用户时间线时,我总是得到失败的响应,作为:{“errors”:[{“code”:215,“message”:“BadAuthentic

  6. ios – 在Swift中将输入字段字符串转换为Int

    所以我非常擅长制作APP广告Swift,我试图在文本字段中做一些非常简单的输入,取值,然后将它们用作Int进行某些计算.但是’vardistance’有些东西不正确它是导致错误的最后一行代码.它说致命错误:无法解开Optional.None解决方法在你的例子中,距离是一个Int?否则称为可选的Int..toInt()返回Int?因为从String到Int的转换可能失败.请参阅以下示例:

  7. 如何在iOS中检测文本(字符串)语言?

    例如,给定以下字符串:我想检测每个声明的字符串中使用的语言.让我们假设已实现函数的签名是:如果没有检测到语言,则返回可选字符串.因此,适当的结果将是:有一个简单的方法来实现它吗?

  8. xamarin – 崩溃在AccountStore.Create().保存(e.Account,“);

    在Xamarin.Forms示例TodoAwsAuth中https://developer.xamarin.com/guides/xamarin-forms/web-services/authentication/oauth/成功登录后,在aOnAuthenticationCompleted事件中,应用程序在尝试保存到Xamarin.Auth时崩溃错误说不能对钥匙串说期待着寻求帮助.解决方法看看你

  9. ios – 将视频分享到Facebook

    我正在编写一个简单的测试应用程序,用于将视频从iOS上传到Facebook.由于FacebookSDK的所有文档都在Objective-C中,因此我发现很难在线找到有关如何使用Swift执行此操作的示例/教程.到目前为止我有这个在我的UI上放置一个共享按钮,但它看起来已禁用,从我读到的这是因为没有内容设置,但我看不出这是怎么可能的.我的getVideoURL()函数返回一个NSURL,它肯定包含视

  10. xcode – 错误“线程1:断点2.1”

    我正在研究RESTAPI管理器.这是一个错误,我无法解决它.我得到的错误在下面突出显示.当我打电话给这个班级获取资源时:我评论的线打印:Thread1:breakpoint2.1我需要修复错误的建议.任何建议都非常感谢解决方法您可能在不注意的情况下意外设置了断点.单击并拖动代表断路器外部断点的蓝色刻度线以将其擦除.

随机推荐

  1. 数组 – Perl中有什么神奇的数组?

    在Perldocumentationforreverse中,我发现:“请注意,将数组反转到自身(如@a=reverse@a)将尽可能保留不存在的元素;即对于非魔法数组或具有EXISTS和DELETE方法的绑定数组.什么属性区分神奇和非魔法阵列?解决方法一个神奇的阵列是一个执行它的操作不仅仅是改变内容.只有内置的魔术阵列是@ISA,而且这是非常不明显的.正如句子所暗示的,魔术阵列主要是一个绑定的阵列

  2. perl – 使用“isa”方法的最佳方式?

    什么是“最好的”使用方式“isa()”可靠?解决方法Scalar::Util实现明确更好.它避免了eval{}的开销,它总是导致设置一个附加变量.Scalar::Util实现更容易阅读.如果eval也失败了,我相信发生的是你在树之前向后走到eval之前的状态–这是如何实现复位状态.这带来了额外的故障开销.基准根本不是一个对象对象传递isa检查对象出现故障现象检查测试代码:我使用这是为i486-linux-gnu-thread-multi建立的perl,v5.10.1(*),以及Scalar::Util,1

  3. 在CORE :: GLOBAL中哪些Perl内置函数不能被覆盖?

    解决方法toke.c中任何值为负的值都可以被覆盖;所有其他人可能不会.你可以看源码here.例如,我们来看看第10,396行的waitpid:由于waitpid为负数,因此可能会被覆盖.grep怎么样?这是积极的,所以不能被覆盖.这意味着以下关键字不能被覆盖:chop,defined,delete,do,dump,each,else,elsif,eval,exists,for,foreach,format,glob,goto,grep,if,keys,last,local,m,map,my,next,no

  4. 如何在Perl中打印由换行符分隔的列表元素?

    什么是最简单的打印所有列表的元素以Perl中的换行符分隔的元素?解决方法在Perl5.10中:其他方式:或:或者怎么样?

  5. 使用Perl如何获取文件大小(以兆字节为单位)?

    我想以磁盘的形式获取磁盘上的文件大小.使用-s运算符给出了以字节为单位的大小,但是我将假设,然后将其除以魔术数字是一个坏主意:我应该使用只读变量来定义1024,还是有一种编程方式来获取一千字节的字节数?

  6. perl – 如何测试/分类CPAN模块的utf8正确性

    例如:File::Slurp,如果你将读取该文件您将根据命令行开关获得不同的结果,并且perl-CSDA将无法正常工作.伤心.(是的,我知道比Encode::decode(“utf8”,read_file($file,binmode=>’:raw’));将帮助,但是SAD.我的问题:>在这里任何首选方式,如何测试/分类什么CPAN模块是utf8安全/准备/正确?>这里是像Perl::Criticforutf8这样的东西–什么将检查模块源可能的utf8不正确?总结以上是DEVMAX为你收集整理的perl–如

  7. 如何删除Perl字符串中的空格?

    如果我声明一个值为’3’的变量$myString.是否有任何功能来删除返回值的空格.有点像SomeFun然后返回’3′.输出:你可以注意到’vid’=>‘0’,上面的代码从theanswer.我正在研究它.总结以上是DEVMAX为你收集整理的如何删除Perl字符串中的空格?如果觉得DEVMAX网站内容还不错,欢迎将DEVMAX网站推荐给好友。

  8. 如何在mod_perl2下运行Devel :: Cover?

    Unfortunately,Devel::Coverdoesnotyetworkwiththreads.它也不适用于prefork.在startup.pl中使用,Devel::Cover问题perl5.8.9,Apache2.2.13.我的操作系统是FreeBSD,如果重要.同样的问题是reportedforwin32.更新:PerlTrace全部输出解决方法邪恶之源似乎是Apache::DBI.

  9. 如何使用Perl中的C类?

    我有一套用C写的课.从Perl脚本中调用它们的最佳方法是什么?

  10. perl – 在Emacs中以双模式更好的缩进

    我正在使用Emacs来修改Perl和Verilog交织的代码.我正在使用two-mode-mode在两者之间切换,这样可以预期.问题是perl代码与//一行一行地表示;如下图所示:而双模式则认识到它是Perl,它是逐行的,所以缩进等在线上无意义.我想做的是使Perl代码像往常一样格式化,但忽略//;字符.有什么想法吗?我刚刚开始偷看模式文件,它们是可以理解的复杂的,所以任何提示都不会感激!

返回
顶部