Bug 677807
| Summary: | Object-valued fields in persisting classes are write-once | ||
|---|---|---|---|
| Product: | Red Hat Enterprise MRG | Reporter: | Will Benton <willb> |
| Component: | ruby-rhubarb | Assignee: | Will Benton <willb> |
| Status: | CLOSED ERRATA | QA Contact: | Tomas Rusnak <trusnak> |
| Severity: | low | Docs Contact: | |
| Priority: | low | ||
| Version: | 1.3 | CC: | matt, mkudlej, rrati, trusnak |
| Target Milestone: | 2.0 | ||
| Target Release: | --- | ||
| Hardware: | Unspecified | ||
| OS: | Unspecified | ||
| Whiteboard: | |||
| Fixed In Version: | rhubarb-0.3.0-1 | Doc Type: | Bug Fix |
| Doc Text: |
C: The rhubarb library supports serializing arbitrary Ruby objects as members of persistent objects, but these fields could only be assigned to once.
C: This behavior is unexpected and undesirable for clients of rhubarb other than wallaby.
F: Object-valued fields can now be updated via the assignment operator, just like other database-backed fields of persisting objects.
R: Object-valued fields can be updated an arbitrary number of times.
Summary: It is now possible to use the Rhubarb persistence library to declare persisting classes with mutable object-valued fields; previously, object-valued fields could only be written once per object.
|
Story Points: | --- |
| Clone Of: | Environment: | ||
| Last Closed: | 2011-06-23 15:42:30 UTC | Type: | --- |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
| Bug Depends On: | |||
| Bug Blocks: | 693778 | ||
Fixed in master.
Technical note added. If any revisions are required, please edit the "Technical Notes" field
accordingly. All revisions will be proofread by the Engineering Content Services team.
New Contents:
C: The rhubarb library supports serializing arbitrary Ruby objects as members of persistent objects, but these fields could only be assigned to once.
C: This behavior is unexpected and undesirable for clients of rhubarb other than wallaby.
F: Object-valued fields can now be updated via the assignment operator, just like other database-backed fields of persisting objects.
R: Object-valued fields can be updated an arbitrary number of times.
Summary: It is now possible to use the Rhubarb persistence library to declare persisting classes with mutable object-valued fields; previously, object-valued fields could only be written once per object.
Reproduced on RHEL5/x86_64:
# rpm -q ruby-rhubarb
ruby-rhubarb-0.2.7-1.el5
# irb
irb(main):001:0> require 'rhubarb/rhubarb'
=> true
irb(main):002:0>
irb(main):003:0* # Create a rhubarb class like this:
irb(main):004:0*
irb(main):005:0* class Foo
irb(main):006:1> include Rhubarb::Persisting
irb(main):007:1> declare_column :ls, :object
irb(main):008:1> end
=> #<Proc:0x00002b70065ec8c8@/usr/lib/ruby/site_ruby/1.8/rhubarb/classmixins.rb:175>
irb(main):009:0>
irb(main):010:0* Rhubarb::Persistence::open(":memory:")
=> #<SQLite3::Database:0x2b7009f64c40 @driver=#<SQLite3::Driver::Native::Driver:0x2b7009f64b00 @callback_data={}, @trace={}, @busy_handler={}, @authorizer={}>, @transaction_active=false, @closed=false, @handle=#<SWIG::TYPE_p_sqlite3:0x2b7009f54ea8>, @translator=nil, @statement_factory=SQLite3::Statement, @type_translation=true, @results_as_hash=true>
irb(main):011:0> Foo.create_table
=> []
irb(main):012:0>
irb(main):013:0* # Then make an instance of that class and manipulate its ls member
irb(main):014:0*
irb(main):015:0* f = Foo.create(:ls=>[1,2,3])
=> #<Foo:0x2b7009f0c108 @updated=1304525095659959, @row_id=1, @created=1304525095659959, @expired_after=1304525095661447, @tuple={"row_id"=>1, 0=>1, 1=>1304525095659959, 2=>1304525095659959, 3=>"x\332\323\325\325U\340\322U0\004b# 6\346\002\000\025\255\002M", "ls"=>"x\332\323\325\325U\340\322U0\004b# 6\346\002\000\025\255\002M", "created"=>1304525095659959, "updated"=>1304525095659959}, @backed=true>
irb(main):016:0> f.ls = f.ls.reverse
SQLite3::SQLException: database table is locked
from /usr/lib/ruby/site_ruby/1.8/sqlite3/errors.rb:62:in `check'
from /usr/lib/ruby/site_ruby/1.8/sqlite3/resultset.rb:56:in `check'
from /usr/lib/ruby/site_ruby/1.8/sqlite3/resultset.rb:48:in `commence'
from /usr/lib/ruby/site_ruby/1.8/sqlite3/resultset.rb:38:in `initialize'
from /usr/lib/ruby/site_ruby/1.8/sqlite3/statement.rb:135:in `new'
from /usr/lib/ruby/site_ruby/1.8/sqlite3/statement.rb:135:in `execute'
from /usr/lib/ruby/site_ruby/1.8/sqlite3/statement.rb:159:in `execute!'
from /usr/lib/ruby/site_ruby/1.8/rhubarb/persistence.rb:19:in `do_query'
from /usr/lib/ruby/site_ruby/1.8/rhubarb/persisting.rb:122:in `update'
from /usr/lib/ruby/site_ruby/1.8/rhubarb/classmixins.rb:177:in `ls='
from (irb):16
irb(main):017:0> f.ls == [3,2,1] # should be true
=> false
Retested on all supported platforms x86,x86_64/RHEL5,RHEL6:
# rpm -q ruby-rhubarb
ruby-rhubarb-0.3.0-2.el6.noarch
# irb
irb(main):001:0> require 'rhubarb/rhubarb'
=> true
irb(main):002:0>
irb(main):003:0* # Create a rhubarb class like this:
irb(main):004:0*
irb(main):005:0* class Foo
irb(main):006:1> include Rhubarb::Persisting
irb(main):007:1> declare_column :ls, :object
irb(main):008:1> end
=> #<Proc:0x00007f51f8112a00@/usr/lib/ruby/site_ruby/1.8/rhubarb/classmixins.rb:181>
irb(main):009:0>
irb(main):010:0* Rhubarb::Persistence::open(":memory:")
=> #<SQLite3::Database:0x7f51f80a8330 @translator=nil, @statement_factory=SQLite3::Statement, @type_translation=true, @results_as_hash=true, @driver=#<SQLite3::Driver::Native::Driver:0x7f51f80a81f0 @authorizer={}, @callback_data={}, @trace={}, @busy_handler={}>, @transaction_active=false, @closed=false, @handle=#<SWIG::TYPE_p_sqlite3:0x7f51f807fde0>>
irb(main):011:0> Foo.create_table
=> []
irb(main):012:0>
irb(main):013:0* # Then make an instance of that class and manipulate its ls member
irb(main):014:0*
irb(main):015:0* f = Foo.create(:ls=>[1,2,3])
=> #<Foo:0x7f51f7392c18 @tuple={"row_id"=>1, 0=>1, 1=>1304525240081866, 2=>1304525240081866, 3=>"x\332\323\325\325U\340\322U0\004b# 6\346\002\000\025\255\002M", "ls"=>"x\332\323\325\325U\340\322U0\004b# 6\346\002\000\025\255\002M", "updated"=>1304525240081866, "created"=>1304525240081866}, @backed=true, @updated=1304525240081866, @row_id=1, @created=1304525240081866, @expired_after=1304525240091020>
irb(main):016:0> f.ls = f.ls.reverse
=> [3, 2, 1]
irb(main):017:0> f.ls == [3,2,1] # should be true
=> true
Looks good on RHEL6 systems.
# rpm -q ruby-rhubarb
ruby-rhubarb-0.3.0-2.el5
# irb
irb(main):001:0> require 'rhubarb/rhubarb'
=> true
irb(main):002:0>
irb(main):003:0* # Create a rhubarb class like this:
irb(main):004:0*
irb(main):005:0* class Foo
irb(main):006:1> include Rhubarb::Persisting
irb(main):007:1> declare_column :ls, :object
irb(main):008:1> end
=> #<Proc:0x00002b3b87734fb8@/usr/lib/ruby/site_ruby/1.8/rhubarb/classmixins.rb:181>
irb(main):009:0>
irb(main):010:0* Rhubarb::Persistence::open(":memory:")
=> #<SQLite3::Database:0x2b3b8b0ac6b0 @driver=#<SQLite3::Driver::Native::Driver:0x2b3b8b0ac570 @callback_data={}, @trace={}, @busy_handler={}, @authorizer={}>, @transaction_active=false, @closed=false, @handle=#<SWIG::TYPE_p_sqlite3:0x2b3b8b09c490>, @translator=nil, @statement_factory=SQLite3::Statement, @type_translation=true, @results_as_hash=true>
irb(main):011:0> Foo.create_table
=> []
irb(main):012:0>
irb(main):013:0* # Then make an instance of that class and manipulate its ls member
irb(main):014:0*
irb(main):015:0* f = Foo.create(:ls=>[1,2,3])
=> #<Foo:0x2b3b8b04fb40 @backed=true, @tuple={"row_id"=>1, 0=>1, 1=>1304525309659463, 2=>1304525309659463, 3=>"x\332\323\325\325U\340\322U0\004b# 6\346\002\000\025\255\002M", "ls"=>"x\332\323\325\325U\340\322U0\004b# 6\346\002\000\025\255\002M", "created"=>1304525309659463, "updated"=>1304525309659463}, @updated=1304525309659463, @row_id=1, @created=1304525309659463, @expired_after=1304525309660828>
irb(main):016:0> f.ls = f.ls.reverse
SQLite3::SQLException: database table is locked
from /usr/lib/ruby/site_ruby/1.8/sqlite3/errors.rb:62:in `check'
from /usr/lib/ruby/site_ruby/1.8/sqlite3/resultset.rb:56:in `check'
from /usr/lib/ruby/site_ruby/1.8/sqlite3/resultset.rb:48:in `commence'
from /usr/lib/ruby/site_ruby/1.8/sqlite3/resultset.rb:38:in `initialize'
from /usr/lib/ruby/site_ruby/1.8/sqlite3/statement.rb:135:in `new'
from /usr/lib/ruby/site_ruby/1.8/sqlite3/statement.rb:135:in `execute'
from /usr/lib/ruby/site_ruby/1.8/sqlite3/statement.rb:159:in `execute!'
from /usr/lib/ruby/site_ruby/1.8/rhubarb/persistence.rb:19:in `do_query'
from /usr/lib/ruby/site_ruby/1.8/rhubarb/persisting.rb:126:in `update'
from /usr/lib/ruby/site_ruby/1.8/rhubarb/classmixins.rb:184:in `ls='
from (irb):16
irb(main):017:0> f.ls == [3,2,1] # should be true
=> false
Testing script failed on both RHEL5 systems - x86 and x86_64.
Bad test script used for RHEL5, retested with repaired one:
# irb
irb(main):001:0> #!/bin/ruby
irb(main):002:0*
irb(main):003:0* require 'rhubarb/rhubarb'
=> true
irb(main):004:0>
irb(main):005:0* # Create a rhubarb class like this:
irb(main):006:0*
irb(main):007:0* class Foo
irb(main):008:1> include Rhubarb::Persisting
irb(main):009:1> declare_column :ls, :object
irb(main):010:1> end
=> #<Proc:0x00002af8c359cc70@/usr/lib/ruby/site_ruby/1.8/rhubarb/classmixins.rb:181>
irb(main):011:0>
irb(main):012:0* Rhubarb::Persistence::open(":memory:", :default, false)
=> #<SQLite3::Database:0x2af8c6f13300 @driver=#<SQLite3::Driver::Native::Driver:0x2af8c6f131c0 @callback_data={}, @trace={}, @busy_handler={}, @authorizer={}>, @transaction_active=false, @closed=false, @handle=#<SWIG::TYPE_p_sqlite3:0x2af8c6f02be0>, @translator=nil, @statement_factory=SQLite3::Statement, @type_translation=true, @results_as_hash=true>
irb(main):013:0> #Rhubarb::Persistence::open(":memory:")
irb(main):014:0* Foo.create_table
=> []
irb(main):015:0>
irb(main):016:0* # Then make an instance of that class and manipulate its ls member
irb(main):017:0*
irb(main):018:0* f = Foo.create(:ls=>[1,2,3])
=> #<Foo:0x2af8c6ead168 @backed=true, @tuple={"row_id"=>1, 0=>1, 1=>1304526044537869, 2=>1304526044537869, 3=>"x\332\323\325\325U\340\322U0\004b# 6\346\002\000\025\255\002M", "ls"=>"x\332\323\325\325U\340\322U0\004b# 6\346\002\000\025\255\002M", "created"=>1304526044537869, "updated"=>1304526044537869}, @updated=1304526044537869, @row_id=1, @created=1304526044537869, @expired_after=1304526044539326>
irb(main):019:0> f.ls = f.ls.reverse
=> [3, 2, 1]
irb(main):020:0> f.ls == [3,2,1] # should be true
=> true
>>> VERIFIED
An advisory has been issued which should help the problem described in this bug report. This report is therefore being closed with a resolution of ERRATA. For more information on therefore solution and/or where to find the updated files, please follow the link below. You may reopen this bug report if the solution does not work for you. http://rhn.redhat.com/errata/RHEA-2011-0889.html |
Description of problem: The rhubarb library supports serializing arbitrary Ruby objects as members of persistent objects. However, this support does not extend to updating object-valued fields in persistent objects. Version-Release number of selected component (if applicable): ruby-rhubarb-0.2.7 How reproducible: Enter the following code into an irb session: ---snip--- require 'rhubarb/rhubarb' # Create a rhubarb class like this: class Foo include Rhubarb::Persisting declare_column :ls, :object end Rhubarb::Persistence::open(":memory:") Foo.create_table # Then make an instance of that class and manipulate its ls member f = Foo.create(:ls=>[1,2,3]) f.ls = f.ls.reverse f.ls == [3,2,1] # should be true ---snip--- Actual results: The assignment in the penultimate line will fail, either silently or with an exception. Expected results: The assignment in the penultimate line should update the persistent object appropriately.