Ruby 错误:can't add a new key into hash during iteration (RuntimeError)

jpwangluo · May 05, 2016 · Last by gobonem replied at March 05, 2024 · 2672 hits

在用 SQLAnywhere 连接 Sybase IQ,有以下程序:

def db_query( dbh, sql )
    sth = dbh.execute(sql)
    print "# of Fields:  #{sth.column_names.size}\n"
    sth.fetch do |row|
        print "\n"
        sth.column_info.each_with_index do |info, i|
            unless info["type_name"] == "LONG VARBINARY"
                print "#{info["name"]}=#{row[i]}\n" 
            end 
        end 
    end 
    sth.finish
end

程序的完整地址:http://dcx.sap.com/sa160/fr/dbprogramming/pg-ruby-dbi.html 调用改程序进行查询,出现错误:

/home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/columninfo.rb:49:in `[]=': can't add a new key into hash during iteration (RuntimeError)
        from /home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/columninfo.rb:49:in `block in initialize'
        from /home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/columninfo.rb:42:in `each_key'
        from /home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/columninfo.rb:42:in `initialize'
        from /home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/handles/statement.rb:185:in `new'
        from /home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/handles/statement.rb:185:in `block in column_info'
        from /home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/handles/statement.rb:185:in `collect'
        from /home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/handles/statement.rb:185:in `column_info'
        from Conn2IQ3.rb:29:in `db_select'
        from Conn2IQ3.rb:59:in `<main>'

这是什么原因?

终于查清楚原因了,是 dbi 包自身的问题,修改 dbi 的源代码如下: 源代码

@hash.each_key do |x|
    if x.kind_of? String
        sym = x.to_sym
        if @hash.has_key? sym
            raise ::TypeError, 
                "#{self.class.name} may construct from a hash keyed with strings or symbols, but not both" 
        end
        @hash[sym] = @hash[x]
        @hash.delete(x)
    end
end

修改为如下:

hash_size = @hash.size()
keys = @hash.keys
#puts "#{keys}"
#puts hash_size
for i in 0..hash_size-1
  keyi = keys[i]
  #puts "#{keyi}"
  if keys[i].kind_of? String
    sym = keyi.to_sym
    if @hash.has_key? sym 
      raise ::TypeError, "#{self.class.name} may construct from a hash keyed with strings or symbols, but not both" 
    end 
    @hash[sym] = @hash[keyi]
    @hash.delete(keyi)
  end 
end 
a = {a: 1, b: 2}
a.each { |k, v| a[v] = a[k] } # will raise "can't add a new key into hash during iteration"
a.dup.each { |k, v| a[v] = a[k] } # works

#2 楼 @angelfan 照这种方法也可以解决

This error needs to be fixed immediately so that queries can continue to run smoothly. It is challenging to encounter such problem while working with iq test free!

You need to Sign in before reply, if you don't have an account, please Sign up first.