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

jpwangluo · 2016年05月05日 · 最后由 jpwangluo 回复于 2016年05月14日 · 2320 次阅读

在用 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 照这种方法也可以解决

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册