Ruby DBI select_all vs execute-fetch / each-finish

这是我使用DBI的示例代码:

dbh = DBI.connect("DBI:Mysql:host=#{server};database=mysql", user, pass) rows = dbh.select_all("SHOW TABLES") 

这里的行打印如下:

 [["user"], ["user"], ["user"], ["user"], ["user"], ["user"], ["user"], ["user"], ["user"], ["user"], ["user"], ["user"], ["user"], ["user"], ["user"], ["user"], ["user"]] 

这是在mysql数据库中打印最后一个表,但记录总数是正确的。

如果我使用execute-fetch / each-finish序列执行此操作,如下所示:

 sth = dbh.execute("SHOW TABLES") sth.each do |row| rows << row[0] end sth.finish 

但它给了我正确的结果,如:

 ["columns_priv", "db", "func", "help_category", "help_keyword", "help_relation", "help_topic", "host", "proc", "procs_priv", "tables_priv", "time_zone", "time_z one_leap_second", "time_zone_name", "time_zone_transition", "time_zone_transitio n_type", "user"] 

帮我解决这个问题?

当我使用DBI.connect("DBI:ODBC:Driver={SQL Server};...")查询MS SQL DB时,也会发生同样的情况DBI.connect("DBI:ODBC:Driver={SQL Server};...")

我的工作是强行将DBI :: Row转换为数组:

 sth = dbh.execute "..." begin return sth.map{ |row| row.to_a } ensure sth.finish end 

我敢打赌1000美元,这个问题与缓冲区重用有关 – 一种可能的“性能”增强,它具有不可抗拒的副作用!

我猜dbh.select_all返回一个Enumerator实例,它在每次迭代时产生相同的行。 看到这个伪代码来理解我的意思:

 def select_all(query) db_row = Row.new reader = @connection.execute_reader(query) Enumerator.new do |yielder| until reader.end? db_row.populate_from(reader) yielder.yield db_row reader.next! end end end 

因此,如果您使用select_all而不使用块,则将返回一个枚举器,它基本上产生相同的db_row对象。

这只是猜测,但我相信事实就在附近。

UPD:这里的源代码https://github.com/erikh/ruby-dbi/blob/master/lib/dbi/handles/statement.rb (请参阅获取方法定义)说我错了,因为@row是重复的在每次迭代。 好吧,可能错误是堆栈的某个地方……