sequel_postgresql_triggers 1.0.8 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 12a05702b972f0adb894a4c5e678400debab6f7a
4
- data.tar.gz: cd51e2bf9105506ed4d992a2eafa231c45346ad4
3
+ metadata.gz: c908ae3d087271626842952b60bc22365793a3d9
4
+ data.tar.gz: 1cf7c4c70437c36ab0852d566d600756314c90d5
5
5
  SHA512:
6
- metadata.gz: cfcd7fe87e24a790f79c1158fabd01f38f0411ad4632e5b4c2a18cce5e27dab8cb32832f8b3a8edd14d879f6427e6bd00c231409db5f2740b8dd9104cc5be833
7
- data.tar.gz: ff1c7f9c541f44e00217e65ed434a16b45e1418517f47e76c1df84590a548fc021f5d3a54454ddca403256c1dc80c2f55b4d0b8ebf202097eceb4d475a8829aa
6
+ metadata.gz: 6f10299a3e24a54147217af11e85317484b02b43a0f9faba1120f5f1bfdd402b8f281c4b403f0f785175c94196d6079a9719667965383102e5732f6e0ca1c9b9
7
+ data.tar.gz: 06f7baa57db107b2fec9d169ebe03f87b737f611adbc302e8af3f0dda2695d0c96d74dd68b50be4b1c7cb0715c4f40b1b17318f41bdf1ed2755defdf94e70ea2
@@ -1,4 +1,4 @@
1
- Copyright (c) 2008-2014 Jeremy Evans
1
+ Copyright (c) 2008-2016 Jeremy Evans
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to
data/README CHANGED
@@ -37,13 +37,21 @@ differs that upon update, the column is also set to CURRENT_TIMESTAMP.
37
37
  This takes quite a few arguments (see the RDoc) and sets up a
38
38
  counter cache so that when the counted table is inserted to
39
39
  or deleted from, records in the main table are updated with the
40
- count of the corresponding records in the counted table.
40
+ count of the corresponding records in the counted table. The counter
41
+ cache column must have a default of 0 for this to work correctly.
41
42
 
42
43
  === Sum Cache - pgt_sum_cache
43
44
 
44
45
  Similar to pgt_counter_cache, except instead of storing a count
45
46
  of records in the main table, it stores the sum on one of the
46
- columns in summed table.
47
+ columns in summed table. The sum cache column must have a default
48
+ of 0 for this to work correctly.
49
+
50
+ === Sum Through Many Cache - pgt_sum_through_many_cache
51
+
52
+ Similar to pgt_sum_cache, except instead of a one-to-many relationship,
53
+ it supports a many-to-many relationship with a single join table. The
54
+ sum cache column must have a default of 0 for this to work correctly.
47
55
 
48
56
  === Immutable Columns - pgt_immutable
49
57
 
@@ -137,6 +137,89 @@ module Sequel
137
137
  SQL
138
138
  end
139
139
 
140
+ # Turns a column in the main table into a sum cache through a join table.
141
+ # A sum cache is a column in the main table with the sum of a column in the
142
+ # summed table for the matching id. The join table must have NOT NULL constraints
143
+ # on the foreign keys to the main table and summed table and a
144
+ # composite unique constraint on both foreign keys.
145
+ #
146
+ # Arguments:
147
+ # * opts : option hash, see module documentation, and below.
148
+ # * :main_table: name of table holding sum cache column
149
+ # * :main_table_id_column: primary key column in main table referenced by main_table_fk_column (default: :id)
150
+ # * :sum_column: column in main table containing the sum cache, must be NOT NULL and default to 0
151
+ # * :summed_table: name of table being summed
152
+ # * :summed_table_id_column: primary key column in summed_table referenced by summed_table_fk_column (default: ;id)
153
+ # * :summed_column: column in summed_table being summed, must be NOT NULL
154
+ # * :join_table: name of table which joins main_table with summed_table
155
+ # * :main_table_fk_column: column in join_table referencing main_table_id_column, must be NOT NULL
156
+ # * :summed_table_fk_column: column in join_table referencing summed_table_id_column, must be NOT NULL
157
+ def pgt_sum_through_many_cache(opts={})
158
+ main_table = opts.fetch(:main_table)
159
+ main_table_id_column = opts.fetch(:main_table_id_column, :id)
160
+ sum_column = opts.fetch(:sum_column)
161
+ summed_table = opts.fetch(:summed_table)
162
+ summed_table_id_column = opts.fetch(:summed_table_id_column, :id)
163
+ summed_column = opts.fetch(:summed_column)
164
+ join_table = opts.fetch(:join_table)
165
+ main_table_fk_column = opts.fetch(:main_table_fk_column)
166
+ summed_table_fk_column = opts.fetch(:summed_table_fk_column)
167
+
168
+ trigger_name = opts[:trigger_name] || "pgt_stmc_#{main_table}__#{main_table_id_column}__#{sum_column}__#{summed_table_id_column}__#{summed_column}__#{main_table_fk_column}__#{summed_table_fk_column}"
169
+ function_name = opts[:function_name] || "pgt_stmc_#{main_table}__#{main_table_id_column}__#{sum_column}__#{summed_table}__#{summed_table_id_column}__#{summed_column}__#{join_table}__#{main_table_fk_column}__#{summed_table_fk_column}"
170
+ join_trigger_name = opts[:join_trigger_name] || "pgt_stmc_join_#{main_table}__#{main_table_id_column}__#{sum_column}__#{summed_table_id_column}__#{summed_column}__#{main_table_fk_column}__#{summed_table_fk_column}"
171
+ join_function_name = opts[:join_function_name] || "pgt_stmc_join_#{main_table}__#{main_table_id_column}__#{sum_column}__#{summed_table}__#{summed_table_id_column}__#{summed_column}__#{join_table}__#{main_table_fk_column}__#{summed_table_fk_column}"
172
+
173
+ orig_summed_table = summed_table
174
+ orig_join_table = join_table
175
+
176
+ main_table = quote_schema_table(main_table)
177
+ main_table_id_column = quote_schema_table(main_table_id_column)
178
+ sum_column = quote_schema_table(sum_column)
179
+ summed_table = quote_schema_table(summed_table)
180
+ summed_table_id_column = quote_schema_table(summed_table_id_column)
181
+ summed_column = quote_schema_table(summed_column)
182
+ join_table = quote_schema_table(join_table)
183
+ main_table_fk_column = quote_schema_table(main_table_fk_column)
184
+ summed_table_fk_column = quote_schema_table(summed_table_fk_column)
185
+
186
+ pgt_trigger(orig_summed_table, trigger_name, function_name, [:insert, :delete, :update], <<-SQL)
187
+ BEGIN
188
+ IF (TG_OP = 'UPDATE' AND NEW.#{summed_table_id_column} = OLD.#{summed_table_id_column}) THEN
189
+ UPDATE #{main_table} SET #{sum_column} = #{sum_column} + NEW.#{summed_column} - OLD.#{summed_column} WHERE #{main_table_id_column} IN (SELECT #{main_table_fk_column} FROM #{join_table} WHERE #{summed_table_fk_column} = NEW.#{summed_table_id_column});
190
+ ELSE
191
+ IF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
192
+ UPDATE #{main_table} SET #{sum_column} = #{sum_column} + NEW.#{summed_column} WHERE #{main_table_id_column} IN (SELECT #{main_table_fk_column} FROM #{join_table} WHERE #{summed_table_fk_column} = NEW.#{summed_table_id_column});
193
+ END IF;
194
+ IF (TG_OP = 'DELETE' OR TG_OP = 'UPDATE') THEN
195
+ UPDATE #{main_table} SET #{sum_column} = #{sum_column} - OLD.#{summed_column} WHERE #{main_table_id_column} IN (SELECT #{main_table_fk_column} FROM #{join_table} WHERE #{summed_table_fk_column} = OLD.#{summed_table_id_column});
196
+ END IF;
197
+ END IF;
198
+ IF (TG_OP = 'DELETE') THEN
199
+ RETURN OLD;
200
+ END IF;
201
+ RETURN NEW;
202
+ END;
203
+ SQL
204
+
205
+ pgt_trigger(orig_join_table, join_trigger_name, join_function_name, [:insert, :delete, :update], <<-SQL)
206
+ BEGIN
207
+ IF (NOT (TG_OP = 'UPDATE' AND NEW.#{main_table_fk_column} = OLD.#{main_table_fk_column} AND NEW.#{summed_table_fk_column} = OLD.#{summed_table_fk_column})) THEN
208
+ IF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
209
+ UPDATE #{main_table} SET #{sum_column} = #{sum_column} + (SELECT #{summed_column} FROM #{summed_table} WHERE #{summed_table_id_column} = NEW.#{summed_table_fk_column}) WHERE #{main_table_id_column} = NEW.#{main_table_fk_column};
210
+ END IF;
211
+ IF (TG_OP = 'DELETE' OR TG_OP = 'UPDATE') THEN
212
+ UPDATE #{main_table} SET #{sum_column} = #{sum_column} - (SELECT #{summed_column} FROM #{summed_table} WHERE #{summed_table_id_column} = OLD.#{summed_table_fk_column}) WHERE #{main_table_id_column} = OLD.#{main_table_fk_column};
213
+ END IF;
214
+ END IF;
215
+ IF (TG_OP = 'DELETE') THEN
216
+ RETURN OLD;
217
+ END IF;
218
+ RETURN NEW;
219
+ END;
220
+ SQL
221
+ end
222
+
140
223
  # When rows in a table are updated, touches a timestamp of related rows
141
224
  # in another table.
142
225
  # Arguments:
@@ -1,6 +1,8 @@
1
- #!/usr/bin/env spec
1
+ #!/usr/bin/env ruby
2
2
  require 'rubygems'
3
3
  require 'sequel'
4
+ require 'minitest/spec'
5
+ require 'minitest/autorun'
4
6
 
5
7
  DB = Sequel.connect(ENV['PGT_SPEC_DB']||'postgres:///spgt_test?user=postgres')
6
8
 
@@ -26,7 +28,7 @@ describe "PostgreSQL Triggers" do
26
28
  DB.drop_language(:plpgsql, :cascade=>true) if DB.server_version < 90000
27
29
  end
28
30
 
29
- context "PostgreSQL Counter Cache Trigger" do
31
+ describe "PostgreSQL Counter Cache Trigger" do
30
32
  before do
31
33
  DB.create_table(:accounts){integer :id; integer :num_entries, :default=>0}
32
34
  DB.create_table(:entries){integer :id; integer :account_id}
@@ -39,45 +41,45 @@ describe "PostgreSQL Triggers" do
39
41
  DB.drop_table(:entries, :accounts)
40
42
  end
41
43
 
42
- specify "Should modify counter cache when adding or removing records" do
43
- DB[:accounts].order(:id).select_map(:num_entries).should == [0, 0]
44
+ it "Should modify counter cache when adding or removing records" do
45
+ DB[:accounts].order(:id).select_map(:num_entries).must_equal [0, 0]
44
46
 
45
47
  DB[:entries] << {:id=>1, :account_id=>1}
46
- DB[:accounts].order(:id).select_map(:num_entries).should == [1, 0]
48
+ DB[:accounts].order(:id).select_map(:num_entries).must_equal [1, 0]
47
49
 
48
50
  DB[:entries] << {:id=>2, :account_id=>1}
49
- DB[:accounts].order(:id).select_map(:num_entries).should == [2, 0]
51
+ DB[:accounts].order(:id).select_map(:num_entries).must_equal [2, 0]
50
52
 
51
53
  DB[:entries] << {:id=>3, :account_id=>nil}
52
- DB[:accounts].order(:id).select_map(:num_entries).should == [2, 0]
54
+ DB[:accounts].order(:id).select_map(:num_entries).must_equal [2, 0]
53
55
 
54
56
  DB[:entries].where(:id=>3).update(:account_id=>2)
55
- DB[:accounts].order(:id).select_map(:num_entries).should == [2, 1]
57
+ DB[:accounts].order(:id).select_map(:num_entries).must_equal [2, 1]
56
58
 
57
59
  DB[:entries].where(:id=>2).update(:account_id=>2)
58
- DB[:accounts].order(:id).select_map(:num_entries).should == [1, 2]
60
+ DB[:accounts].order(:id).select_map(:num_entries).must_equal [1, 2]
59
61
 
60
62
  DB[:entries].where(:id=>2).update(:account_id=>nil)
61
- DB[:accounts].order(:id).select_map(:num_entries).should == [1, 1]
63
+ DB[:accounts].order(:id).select_map(:num_entries).must_equal [1, 1]
62
64
 
63
65
  DB[:entries].where(:id=>2).update(:id=>4)
64
- DB[:accounts].order(:id).select_map(:num_entries).should == [1, 1]
66
+ DB[:accounts].order(:id).select_map(:num_entries).must_equal [1, 1]
65
67
 
66
68
  DB[:entries].where(:id=>4).update(:account_id=>2)
67
- DB[:accounts].order(:id).select_map(:num_entries).should == [1, 2]
69
+ DB[:accounts].order(:id).select_map(:num_entries).must_equal [1, 2]
68
70
 
69
71
  DB[:entries].where(:id=>4).update(:account_id=>nil)
70
- DB[:accounts].order(:id).select_map(:num_entries).should == [1, 1]
72
+ DB[:accounts].order(:id).select_map(:num_entries).must_equal [1, 1]
71
73
 
72
74
  DB[:entries].filter(:id=>4).delete
73
- DB[:accounts].order(:id).select_map(:num_entries).should == [1, 1]
75
+ DB[:accounts].order(:id).select_map(:num_entries).must_equal [1, 1]
74
76
 
75
77
  DB[:entries].delete
76
- DB[:accounts].order(:id).select_map(:num_entries).should == [0, 0]
78
+ DB[:accounts].order(:id).select_map(:num_entries).must_equal [0, 0]
77
79
  end
78
80
  end
79
81
 
80
- context "PostgreSQL Created At Trigger" do
82
+ describe "PostgreSQL Created At Trigger" do
81
83
  before do
82
84
  DB.create_table(:accounts){integer :id; timestamp :added_on}
83
85
  DB.pgt_created_at(:accounts, :added_on)
@@ -87,21 +89,21 @@ describe "PostgreSQL Triggers" do
87
89
  DB.drop_table(:accounts)
88
90
  end
89
91
 
90
- specify "Should set the column upon insertion and ignore modifications afterward" do
92
+ it "Should set the column upon insertion and ignore modifications afterward" do
91
93
  DB[:accounts] << {:id=>1}
92
94
  t = DB[:accounts].get(:added_on)
93
- t.strftime('%F').should == Date.today.strftime('%F')
95
+ t.strftime('%F').must_equal Date.today.strftime('%F')
94
96
  DB[:accounts].update(:added_on=>Date.today - 60)
95
- DB[:accounts].get(:added_on).should == t
97
+ DB[:accounts].get(:added_on).must_equal t
96
98
  DB[:accounts] << {:id=>2}
97
99
  ds = DB[:accounts].select(:added_on)
98
- DB[:accounts].select((Sequel::SQL::NumericExpression.new(:NOOP, ds.filter(:id=>2)) > ds.filter(:id=>1)).as(:x)).first[:x].should == true
100
+ DB[:accounts].select((Sequel::SQL::NumericExpression.new(:NOOP, ds.filter(:id=>2)) > ds.filter(:id=>1)).as(:x)).first[:x].must_equal true
99
101
  DB[:accounts].filter(:id=>1).update(:id=>3)
100
- DB[:accounts].select((Sequel::SQL::NumericExpression.new(:NOOP, ds.filter(:id=>2)) > ds.filter(:id=>3)).as(:x)).first[:x].should == true
102
+ DB[:accounts].select((Sequel::SQL::NumericExpression.new(:NOOP, ds.filter(:id=>2)) > ds.filter(:id=>3)).as(:x)).first[:x].must_equal true
101
103
  end
102
104
  end
103
105
 
104
- context "PostgreSQL Immutable Trigger" do
106
+ describe "PostgreSQL Immutable Trigger" do
105
107
  before do
106
108
  DB.create_table(:accounts){integer :id; integer :balance, :default=>0}
107
109
  DB.pgt_immutable(:accounts, :balance)
@@ -112,29 +114,29 @@ describe "PostgreSQL Triggers" do
112
114
  DB.drop_table(:accounts)
113
115
  end
114
116
 
115
- specify "Should allow modifying columns not marked as immutable" do
116
- proc{DB[:accounts].update(:id=>2)}.should_not raise_error
117
+ it "Should allow modifying columns not marked as immutable" do
118
+ DB[:accounts].update(:id=>2)
117
119
  end
118
120
 
119
- specify "Should allow updating a column to its existing value" do
120
- proc{DB[:accounts].update(:balance=>0)}.should_not raise_error
121
- proc{DB[:accounts].update(:balance=>Sequel.*(:balance, :balance))}.should_not raise_error
121
+ it "Should allow updating a column to its existing value" do
122
+ DB[:accounts].update(:balance=>0)
123
+ DB[:accounts].update(:balance=>Sequel.*(:balance, :balance))
122
124
  end
123
125
 
124
- specify "Should not allow modifying a column's value" do
125
- proc{DB[:accounts].update(:balance=>1)}.should raise_error(Sequel::DatabaseError)
126
+ it "Should not allow modifying a column's value" do
127
+ proc{DB[:accounts].update(:balance=>1)}.must_raise(Sequel::DatabaseError)
126
128
  end
127
129
 
128
- specify "Should handle NULL values correctly" do
129
- proc{DB[:accounts].update(:balance=>nil)}.should raise_error(Sequel::DatabaseError)
130
+ it "Should handle NULL values correctly" do
131
+ proc{DB[:accounts].update(:balance=>nil)}.must_raise(Sequel::DatabaseError)
130
132
  DB[:accounts].delete
131
133
  DB[:accounts] << {:id=>1, :balance=>nil}
132
- proc{DB[:accounts].update(:balance=>nil)}.should_not raise_error
133
- proc{DB[:accounts].update(:balance=>0)}.should raise_error(Sequel::DatabaseError)
134
+ DB[:accounts].update(:balance=>nil)
135
+ proc{DB[:accounts].update(:balance=>0)}.must_raise(Sequel::DatabaseError)
134
136
  end
135
137
  end
136
138
 
137
- context "PostgreSQL Sum Cache Trigger" do
139
+ describe "PostgreSQL Sum Cache Trigger" do
138
140
  before do
139
141
  DB.create_table(:accounts){integer :id; integer :balance, :default=>0}
140
142
  DB.create_table(:entries){integer :id; integer :account_id; integer :amount}
@@ -147,48 +149,137 @@ describe "PostgreSQL Triggers" do
147
149
  DB.drop_table(:entries, :accounts)
148
150
  end
149
151
 
150
- specify "Should modify sum cache when adding, updating, or removing records" do
151
- DB[:accounts].order(:id).select_map(:balance).should == [0, 0]
152
+ it "Should modify sum cache when adding, updating, or removing records" do
153
+ DB[:accounts].order(:id).select_map(:balance).must_equal [0, 0]
152
154
 
153
155
  DB[:entries] << {:id=>1, :account_id=>1, :amount=>100}
154
- DB[:accounts].order(:id).select_map(:balance).should == [100, 0]
156
+ DB[:accounts].order(:id).select_map(:balance).must_equal [100, 0]
155
157
 
156
158
  DB[:entries] << {:id=>2, :account_id=>1, :amount=>200}
157
- DB[:accounts].order(:id).select_map(:balance).should == [300, 0]
159
+ DB[:accounts].order(:id).select_map(:balance).must_equal [300, 0]
158
160
 
159
161
  DB[:entries] << {:id=>3, :account_id=>nil, :amount=>500}
160
- DB[:accounts].order(:id).select_map(:balance).should == [300, 0]
162
+ DB[:accounts].order(:id).select_map(:balance).must_equal [300, 0]
161
163
 
162
164
  DB[:entries].where(:id=>3).update(:account_id=>2)
163
- DB[:accounts].order(:id).select_map(:balance).should == [300, 500]
165
+ DB[:accounts].order(:id).select_map(:balance).must_equal [300, 500]
164
166
 
165
167
  DB[:entries].exclude(:id=>2).update(:amount=>Sequel.*(:amount, 2))
166
- DB[:accounts].order(:id).select_map(:balance).should == [400, 1000]
168
+ DB[:accounts].order(:id).select_map(:balance).must_equal [400, 1000]
167
169
 
168
170
  DB[:entries].where(:id=>2).update(:account_id=>2)
169
- DB[:accounts].order(:id).select_map(:balance).should == [200, 1200]
171
+ DB[:accounts].order(:id).select_map(:balance).must_equal [200, 1200]
170
172
 
171
173
  DB[:entries].where(:id=>2).update(:account_id=>nil)
172
- DB[:accounts].order(:id).select_map(:balance).should == [200, 1000]
174
+ DB[:accounts].order(:id).select_map(:balance).must_equal [200, 1000]
173
175
 
174
176
  DB[:entries].where(:id=>2).update(:id=>4)
175
- DB[:accounts].order(:id).select_map(:balance).should == [200, 1000]
177
+ DB[:accounts].order(:id).select_map(:balance).must_equal [200, 1000]
176
178
 
177
179
  DB[:entries].where(:id=>4).update(:account_id=>2)
178
- DB[:accounts].order(:id).select_map(:balance).should == [200, 1200]
180
+ DB[:accounts].order(:id).select_map(:balance).must_equal [200, 1200]
179
181
 
180
182
  DB[:entries].where(:id=>4).update(:account_id=>nil)
181
- DB[:accounts].order(:id).select_map(:balance).should == [200, 1000]
183
+ DB[:accounts].order(:id).select_map(:balance).must_equal [200, 1000]
182
184
 
183
185
  DB[:entries].filter(:id=>4).delete
184
- DB[:accounts].order(:id).select_map(:balance).should == [200, 1000]
186
+ DB[:accounts].order(:id).select_map(:balance).must_equal [200, 1000]
185
187
 
186
188
  DB[:entries].delete
187
- DB[:accounts].order(:id).select_map(:balance).should == [0, 0]
189
+ DB[:accounts].order(:id).select_map(:balance).must_equal [0, 0]
188
190
  end
189
191
  end
190
192
 
191
- context "PostgreSQL Updated At Trigger" do
193
+ describe "PostgreSQL Sum Through Many Cache Trigger" do
194
+ before do
195
+ DB.create_table(:parents){primary_key :id; integer :balance, :default=>0, :null=>false}
196
+ DB.create_table(:children){primary_key :id; integer :amount, :null=>false}
197
+ DB.create_table(:links){integer :parent_id, :null=>false; integer :child_id, :null=>false; unique [:parent_id, :child_id]}
198
+ DB.pgt_sum_through_many_cache(
199
+ :main_table=>:parents,
200
+ :sum_column=>:balance,
201
+ :summed_table=>:children,
202
+ :summed_column=>:amount,
203
+ :join_table=>:links,
204
+ :main_table_fk_column=>:parent_id,
205
+ :summed_table_fk_column=>:child_id
206
+ )
207
+ DB[:parents] << {:id=>1}
208
+ DB[:parents] << {:id=>2}
209
+ end
210
+
211
+ after do
212
+ DB.drop_table(:links, :parents, :children)
213
+ end
214
+
215
+ it "Should modify sum cache when adding, updating, or removing records" do
216
+ DB[:parents].order(:id).select_map(:balance).must_equal [0, 0]
217
+
218
+ DB[:children] << {:id=>1, :amount=>100}
219
+ DB[:links] << {:parent_id=>1, :child_id=>1}
220
+ DB[:parents].order(:id).select_map(:balance).must_equal [100, 0]
221
+
222
+ DB[:children] << {:id=>2, :amount=>200}
223
+ DB[:links] << {:parent_id=>1, :child_id=>2}
224
+ DB[:parents].order(:id).select_map(:balance).must_equal [300, 0]
225
+
226
+ DB[:children] << {:id=>3, :amount=>500}
227
+ DB[:parents].order(:id).select_map(:balance).must_equal [300, 0]
228
+ DB[:links] << {:parent_id=>2, :child_id=>3}
229
+ DB[:parents].order(:id).select_map(:balance).must_equal [300, 500]
230
+
231
+ DB[:links].where(:parent_id=>2, :child_id=>3).update(:parent_id=>1)
232
+ DB[:parents].order(:id).select_map(:balance).must_equal [800, 0]
233
+
234
+ DB[:children] << {:id=>4, :amount=>400}
235
+ DB[:links].where(:parent_id=>1, :child_id=>3).update(:child_id=>4)
236
+ DB[:parents].order(:id).select_map(:balance).must_equal [700, 0]
237
+
238
+ DB[:links].where(:parent_id=>1, :child_id=>4).update(:parent_id=>2, :child_id=>3)
239
+ DB[:parents].order(:id).select_map(:balance).must_equal [300, 500]
240
+
241
+ DB[:children].exclude(:id=>2).update(:amount=>Sequel.*(:amount, 2))
242
+ DB[:parents].order(:id).select_map(:balance).must_equal [400, 1000]
243
+
244
+ DB[:links].where(:parent_id=>1, :child_id=>2).update(:parent_id=>2)
245
+ DB[:parents].order(:id).select_map(:balance).must_equal [200, 1200]
246
+
247
+ DB[:links].where(:parent_id=>2, :child_id=>2).update(:parent_id=>1)
248
+ DB[:parents].order(:id).select_map(:balance).must_equal [400, 1000]
249
+
250
+ DB[:links].where(:parent_id=>1, :child_id=>2).update(:child_id=>3)
251
+ DB[:parents].order(:id).select_map(:balance).must_equal [1200, 1000]
252
+
253
+ DB[:links] << {:parent_id=>2, :child_id=>4}
254
+ DB[:parents].order(:id).select_map(:balance).must_equal [1200, 1800]
255
+
256
+ DB[:children].filter(:id=>4).delete
257
+ DB[:parents].order(:id).select_map(:balance).must_equal [1200, 1000]
258
+
259
+ DB[:links].filter(:parent_id=>1, :child_id=>1).delete
260
+ DB[:parents].order(:id).select_map(:balance).must_equal [1000, 1000]
261
+
262
+ DB[:children] << {:id=>4, :amount=>400}
263
+ DB[:parents].order(:id).select_map(:balance).must_equal [1000, 1400]
264
+
265
+ DB[:children].delete
266
+ DB[:parents].order(:id).select_map(:balance).must_equal [0, 0]
267
+
268
+ DB[:children].multi_insert([{:id=>2, :amount=>200}, {:id=>1, :amount=>200}, {:id=>3, :amount=>1000}, {:id=>4, :amount=>400}])
269
+ DB[:parents].order(:id).select_map(:balance).must_equal [1000, 1400]
270
+
271
+ DB[:links].where(:child_id=>3).update(:child_id=>2)
272
+ DB[:parents].order(:id).select_map(:balance).must_equal [200, 600]
273
+
274
+ DB[:children].update(:amount=>10)
275
+ DB[:parents].order(:id).select_map(:balance).must_equal [10, 20]
276
+
277
+ DB[:links].delete
278
+ DB[:parents].order(:id).select_map(:balance).must_equal [0, 0]
279
+ end
280
+ end
281
+
282
+ describe "PostgreSQL Updated At Trigger" do
192
283
  before do
193
284
  DB.create_table(:accounts){integer :id; timestamp :changed_on}
194
285
  DB.pgt_updated_at(:accounts, :changed_on)
@@ -198,19 +289,19 @@ describe "PostgreSQL Triggers" do
198
289
  DB.drop_table(:accounts)
199
290
  end
200
291
 
201
- specify "Should set the column always to the current timestamp" do
292
+ it "Should set the column always to the current timestamp" do
202
293
  DB[:accounts] << {:id=>1}
203
294
  t = DB[:accounts].get(:changed_on)
204
- t.strftime('%F').should == Date.today.strftime('%F')
295
+ t.strftime('%F').must_equal Date.today.strftime('%F')
205
296
  DB[:accounts] << {:id=>2}
206
297
  ds = DB[:accounts].select(:changed_on)
207
- DB[:accounts].select((Sequel::SQL::NumericExpression.new(:NOOP, ds.filter(:id=>2)) > ds.filter(:id=>1)).as(:x)).first[:x].should == true
298
+ DB[:accounts].select((Sequel::SQL::NumericExpression.new(:NOOP, ds.filter(:id=>2)) > ds.filter(:id=>1)).as(:x)).first[:x].must_equal true
208
299
  DB[:accounts].filter(:id=>1).update(:id=>3)
209
- DB[:accounts].select((Sequel::SQL::NumericExpression.new(:NOOP, ds.filter(:id=>3)) > ds.filter(:id=>2)).as(:x)).first[:x].should == true
300
+ DB[:accounts].select((Sequel::SQL::NumericExpression.new(:NOOP, ds.filter(:id=>3)) > ds.filter(:id=>2)).as(:x)).first[:x].must_equal true
210
301
  end
211
302
  end
212
303
 
213
- context "PostgreSQL Touch Trigger" do
304
+ describe "PostgreSQL Touch Trigger" do
214
305
  before do
215
306
  DB.create_table(:parents){integer :id1; integer :id2; integer :child_id; timestamp :changed_on}
216
307
  DB.create_table(:children){integer :id; integer :parent_id1; integer :parent_id2; timestamp :changed_on}
@@ -220,86 +311,86 @@ describe "PostgreSQL Triggers" do
220
311
  DB.drop_table(:children, :parents)
221
312
  end
222
313
 
223
- specify "Should update the timestamp column of the related table when adding, updating or removing records" do
314
+ it "Should update the timestamp column of the related table when adding, updating or removing records" do
224
315
  DB.pgt_touch(:children, :parents, :changed_on, :id1=>:parent_id1)
225
316
  d = Date.today
226
317
  d30 = Date.today - 30
227
318
  DB[:parents] << {:id1=>1, :changed_on=>d30}
228
319
  DB[:parents] << {:id1=>2, :changed_on=>d30}
229
320
  DB[:children] << {:id=>1, :parent_id1=>1}
230
- DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.should == [d.strftime('%F'), d30.strftime('%F')]
321
+ DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.must_equal [d.strftime('%F'), d30.strftime('%F')]
231
322
 
232
323
  DB[:parents].update(:changed_on=>d30)
233
324
  DB[:children].update(:id=>2)
234
- DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.should == [d.strftime('%F'), d30.strftime('%F')]
325
+ DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.must_equal [d.strftime('%F'), d30.strftime('%F')]
235
326
 
236
327
  DB[:parents].update(:changed_on=>d30)
237
328
  DB[:children].update(:parent_id1=>2)
238
- DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.should == [d.strftime('%F'), d.strftime('%F')]
329
+ DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.must_equal [d.strftime('%F'), d.strftime('%F')]
239
330
 
240
331
  DB[:parents].update(:changed_on=>d30)
241
332
  DB[:children].update(:parent_id1=>nil)
242
- DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.should == [d30.strftime('%F'), d.strftime('%F')]
333
+ DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.must_equal [d30.strftime('%F'), d.strftime('%F')]
243
334
 
244
335
  DB[:parents].update(:changed_on=>d30)
245
336
  DB[:children].update(:parent_id2=>1)
246
- DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.should == [d30.strftime('%F'), d30.strftime('%F')]
337
+ DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.must_equal [d30.strftime('%F'), d30.strftime('%F')]
247
338
 
248
339
  DB[:parents].update(:changed_on=>d30)
249
340
  DB[:children].update(:parent_id1=>2)
250
- DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.should == [d30.strftime('%F'), d.strftime('%F')]
341
+ DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.must_equal [d30.strftime('%F'), d.strftime('%F')]
251
342
 
252
343
  DB[:parents].update(:changed_on=>d30)
253
344
  DB[:children].delete
254
- DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.should == [d30.strftime('%F'), d.strftime('%F')]
345
+ DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.must_equal [d30.strftime('%F'), d.strftime('%F')]
255
346
 
256
347
  DB[:parents].update(:changed_on=>d30)
257
348
  DB[:children] << {:id=>2, :parent_id1=>nil}
258
- DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.should == [d30.strftime('%F'), d30.strftime('%F')]
349
+ DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.must_equal [d30.strftime('%F'), d30.strftime('%F')]
259
350
  DB[:children].where(:id=>2).delete
260
- DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.should == [d30.strftime('%F'), d30.strftime('%F')]
351
+ DB[:parents].order(:id1).select_map(:changed_on).map{|t| t.strftime('%F')}.must_equal [d30.strftime('%F'), d30.strftime('%F')]
261
352
  end
262
353
 
263
- specify "Should update the timestamp column of the related table when there is a composite foreign key" do
354
+ it "Should update the timestamp column of the related table when there is a composite foreign key" do
264
355
  DB.pgt_touch(:children, :parents, :changed_on, :id1=>:parent_id1, :id2=>:parent_id2)
265
356
  DB[:parents] << {:id1=>1, :id2=>2, :changed_on=>Date.today - 30}
266
357
  DB[:children] << {:id=>1, :parent_id1=>1, :parent_id2=>2}
267
- DB[:parents].get(:changed_on).strftime('%F').should == Date.today.strftime('%F')
358
+ DB[:parents].get(:changed_on).strftime('%F').must_equal Date.today.strftime('%F')
268
359
  DB[:parents].update(:changed_on=>Date.today - 30)
269
360
  DB[:children].update(:id=>2)
270
- DB[:parents].get(:changed_on).strftime('%F').should == Date.today.strftime('%F')
361
+ DB[:parents].get(:changed_on).strftime('%F').must_equal Date.today.strftime('%F')
271
362
  DB[:parents].update(:changed_on=>Date.today - 30)
272
363
  DB[:children].delete
273
- DB[:parents].get(:changed_on).strftime('%F').should == Date.today.strftime('%F')
364
+ DB[:parents].get(:changed_on).strftime('%F').must_equal Date.today.strftime('%F')
274
365
  end
275
366
 
276
- specify "Should update timestamps correctly when two tables touch each other" do
367
+ it "Should update timestamps correctly when two tables touch each other" do
277
368
  DB.pgt_touch(:children, :parents, :changed_on, :id1=>:parent_id1)
278
369
  DB.pgt_touch(:parents, :children, :changed_on, :id=>:child_id)
279
370
  DB[:parents] << {:id1=>1, :child_id=>1, :changed_on=>Date.today - 30}
280
371
  DB[:children] << {:id=>1, :parent_id1=>1, :changed_on=>Date.today - 30}
281
- DB[:parents].get(:changed_on).strftime('%F').should == Date.today.strftime('%F')
282
- DB[:children].get(:changed_on).strftime('%F').should == Date.today.strftime('%F')
372
+ DB[:parents].get(:changed_on).strftime('%F').must_equal Date.today.strftime('%F')
373
+ DB[:children].get(:changed_on).strftime('%F').must_equal Date.today.strftime('%F')
283
374
  time = DB[:parents].get(:changed_on)
284
375
  DB[:parents].update(:id2=>4)
285
- DB[:parents].get(:changed_on).should > time
286
- DB[:children].get(:changed_on).should > time
376
+ DB[:parents].get(:changed_on).must_be :>, time
377
+ DB[:children].get(:changed_on).must_be :>, time
287
378
  time = DB[:parents].get(:changed_on)
288
379
  DB[:children].update(:id=>1)
289
- DB[:parents].get(:changed_on).should > time
290
- DB[:children].get(:changed_on).should > time
380
+ DB[:parents].get(:changed_on).must_be :>, time
381
+ DB[:children].get(:changed_on).must_be :>, time
291
382
  time = DB[:parents].get(:changed_on)
292
383
  DB[:children].delete
293
- DB[:parents].get(:changed_on).should > time
384
+ DB[:parents].get(:changed_on).must_be :>, time
294
385
  end
295
386
 
296
- specify "Should update the timestamp on the related table if that timestamp is initially NULL" do
387
+ it "Should update the timestamp on the related table if that timestamp is initially NULL" do
297
388
  DB.pgt_touch(:children, :parents, :changed_on, :id1=>:parent_id1)
298
389
  DB[:parents] << {:id1=>1, :changed_on=>nil}
299
390
  DB[:children] << {:id=>1, :parent_id1=>1}
300
391
  changed_on = DB[:parents].get(:changed_on)
301
- changed_on.should_not == nil
302
- changed_on.strftime('%F').should == Date.today.strftime('%F')
392
+ changed_on.wont_equal nil
393
+ changed_on.strftime('%F').must_equal Date.today.strftime('%F')
303
394
  end
304
395
  end
305
396
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel_postgresql_triggers
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.8
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-07 00:00:00.000000000 Z
11
+ date: 2016-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -62,7 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
62
62
  version: '0'
63
63
  requirements: []
64
64
  rubyforge_project:
65
- rubygems_version: 2.4.5
65
+ rubygems_version: 2.5.1
66
66
  signing_key:
67
67
  specification_version: 4
68
68
  summary: Database enforced timestamps, immutable columns, and counter/sum caches