diff --git a/lib/sequel_postgresql_triggers.rb b/lib/sequel_postgresql_triggers.rb index 39a67e0..da4e751 100644 --- a/lib/sequel_postgresql_triggers.rb +++ b/lib/sequel_postgresql_triggers.rb @@ -78,7 +78,7 @@ def pgt_created_at(table, column, opts={}) # Makes all given columns in the given table immutable, so an exception # is raised if there is an attempt to modify the value when updating the - # record. Arguments: + # record. Allows updating from/to NULL. Arguments: # * table : name of table # * columns : All columns in the table that should be immutable. Can end with a hash of options, see module documentation. def pgt_immutable(table, *columns) @@ -89,7 +89,7 @@ def pgt_immutable(table, *columns) old = "OLD.#{quote_identifier(c)}" new = "NEW.#{quote_identifier(c)}" <<-END - IF #{new} IS DISTINCT FROM #{old} THEN + IF #{new} IS DISTINCT FROM #{old} AND #{old} IS NOT NULL AND #{new} IS NOT NULL THEN RAISE EXCEPTION 'Attempted #{c} update: Old: %, New: %', #{old}, #{new}; END IF; END @@ -142,7 +142,7 @@ def pgt_sum_cache(main_table, main_table_id_column, sum_column, summed_table, su # summed table for the matching id. The join table must have NOT NULL constraints # on the foreign keys to the main table and summed table and a # composite unique constraint on both foreign keys. - # + # # Arguments: # * opts : option hash, see module documentation, and below. # * :main_table: name of table holding sum cache column diff --git a/spec/sequel_postgresql_triggers_spec.rb b/spec/sequel_postgresql_triggers_spec.rb index eac5f58..a2794c1 100644 --- a/spec/sequel_postgresql_triggers_spec.rb +++ b/spec/sequel_postgresql_triggers_spec.rb @@ -49,31 +49,31 @@ DB[:entries] << {:id=>2, :account_id=>1} DB[:accounts].order(:id).select_map(:num_entries).must_equal [2, 0] - + DB[:entries] << {:id=>3, :account_id=>nil} DB[:accounts].order(:id).select_map(:num_entries).must_equal [2, 0] - + DB[:entries].where(:id=>3).update(:account_id=>2) DB[:accounts].order(:id).select_map(:num_entries).must_equal [2, 1] - + DB[:entries].where(:id=>2).update(:account_id=>2) DB[:accounts].order(:id).select_map(:num_entries).must_equal [1, 2] - + DB[:entries].where(:id=>2).update(:account_id=>nil) DB[:accounts].order(:id).select_map(:num_entries).must_equal [1, 1] - + DB[:entries].where(:id=>2).update(:id=>4) DB[:accounts].order(:id).select_map(:num_entries).must_equal [1, 1] - + DB[:entries].where(:id=>4).update(:account_id=>2) DB[:accounts].order(:id).select_map(:num_entries).must_equal [1, 2] - + DB[:entries].where(:id=>4).update(:account_id=>nil) DB[:accounts].order(:id).select_map(:num_entries).must_equal [1, 1] - + DB[:entries].filter(:id=>4).delete DB[:accounts].order(:id).select_map(:num_entries).must_equal [1, 1] - + DB[:entries].delete DB[:accounts].order(:id).select_map(:num_entries).must_equal [0, 0] end @@ -128,11 +128,13 @@ end it "Should handle NULL values correctly" do - proc{DB[:accounts].update(:balance=>nil)}.must_raise(Sequel::DatabaseError) + DB[:accounts].update(:balance=>nil) DB[:accounts].delete DB[:accounts] << {:id=>1, :balance=>nil} DB[:accounts].update(:balance=>nil) - proc{DB[:accounts].update(:balance=>0)}.must_raise(Sequel::DatabaseError) + DB[:accounts].update(:balance=>0) + proc{DB[:accounts].update(:balance=>1)}.must_raise(Sequel::DatabaseError) + DB[:accounts].update(:balance=>nil) end end @@ -157,34 +159,34 @@ DB[:entries] << {:id=>2, :account_id=>1, :amount=>200} DB[:accounts].order(:id).select_map(:balance).must_equal [300, 0] - + DB[:entries] << {:id=>3, :account_id=>nil, :amount=>500} DB[:accounts].order(:id).select_map(:balance).must_equal [300, 0] - + DB[:entries].where(:id=>3).update(:account_id=>2) DB[:accounts].order(:id).select_map(:balance).must_equal [300, 500] - + DB[:entries].exclude(:id=>2).update(:amount=>Sequel.*(:amount, 2)) DB[:accounts].order(:id).select_map(:balance).must_equal [400, 1000] - + DB[:entries].where(:id=>2).update(:account_id=>2) DB[:accounts].order(:id).select_map(:balance).must_equal [200, 1200] - + DB[:entries].where(:id=>2).update(:account_id=>nil) DB[:accounts].order(:id).select_map(:balance).must_equal [200, 1000] - + DB[:entries].where(:id=>2).update(:id=>4) DB[:accounts].order(:id).select_map(:balance).must_equal [200, 1000] - + DB[:entries].where(:id=>4).update(:account_id=>2) DB[:accounts].order(:id).select_map(:balance).must_equal [200, 1200] - + DB[:entries].where(:id=>4).update(:account_id=>nil) DB[:accounts].order(:id).select_map(:balance).must_equal [200, 1000] - + DB[:entries].filter(:id=>4).delete DB[:accounts].order(:id).select_map(:balance).must_equal [200, 1000] - + DB[:entries].delete DB[:accounts].order(:id).select_map(:balance).must_equal [0, 0] end