updateable_views_inheritance 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 1.2.2 (18 August 2015)
2
+
3
+ Bugfixes:
4
+
5
+ - fixed compatibility with Rails 3.2.19+ and ActiveRecord's prepared statements
6
+
1
7
  ## 1.2.1 (27 August 2014)
2
8
 
3
9
  Bugfixes:
data/Gemfile CHANGED
@@ -3,4 +3,9 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in updateable_views_inheritance.gemspec
4
4
  gemspec
5
5
 
6
- gem 'debugger'
6
+ if RUBY_VERSION > "2"
7
+ gem 'byebug'
8
+ else
9
+ gem 'debugger'
10
+ end
11
+
data/README.rdoc CHANGED
@@ -25,11 +25,6 @@ Run
25
25
 
26
26
  * In <tt>Gemfile</tt> add <tt>gem 'updateable_views_inheritance'</tt>
27
27
  * Run <tt>rails generate updateable_views_inheritance:install && rake db:migrate</tt>
28
- * In <tt>config/database.yml</tt> аdd to every environment
29
-
30
- prepared_statements: false
31
-
32
- ActiveRecord's postgresql adapter has subtle problems with prepared statements that cause strange errors every now and then.
33
28
  * In <tt>config/environment.rb</tt> set <tt>config.active_record.schema_format = :sql</tt>
34
29
  * In case you're using fixtures, don't forget to run
35
30
 
@@ -118,4 +113,9 @@ may fail when there are foreign key constraints on tables. To fix this, explicit
118
113
 
119
114
  fixtures :roots, :trunks, :leafs, ...
120
115
 
121
- for all fixtures you want to load.
116
+ for all fixtures you want to load.
117
+
118
+ ==Gem Development & Testing
119
+
120
+ The gem has a comprehensive test suite. In order to run it, your user must be a superuser in PostgreSQL.
121
+ If this is not the case, run <tt>createuser -s pesho</tt> (assuming your Unix account is <tt>pesho</tt>).
data/Rakefile CHANGED
@@ -24,12 +24,12 @@ end
24
24
  namespace :test do
25
25
  desc 'Build the test database'
26
26
  task :create_database do
27
- %x( createdb -U postgres updateable_views_inheritance_test )
27
+ %x( createdb updateable_views_inheritance_test )
28
28
  end
29
29
 
30
30
  desc 'Drop the test database'
31
- task :drop_database do
32
- %x( dropdb -U postgres updateable_views_inheritance_test )
31
+ task :drop_database do
32
+ %x( dropdb updateable_views_inheritance_test )
33
33
  end
34
34
 
35
35
  desc 'Rebuild the test database'
@@ -111,7 +111,7 @@ module ActiveRecord #:nodoc:
111
111
  parent = parent_table(relation)
112
112
  pk_and_sequence_for(parent) if parent
113
113
  else
114
- # log(result[0], "PK for #{relation}")
114
+ # log(result[0], "PK for #{relation}") {}
115
115
  [result[0], query("SELECT pg_get_serial_sequence('#{relation}', '#{result[0]}') ")[0][0]]
116
116
  end
117
117
  rescue
@@ -295,14 +295,13 @@ module ActiveRecord #:nodoc:
295
295
  execute <<-end_sql
296
296
  CREATE OR REPLACE RULE #{quote_column_name("#{child_view}_insert")} AS
297
297
  ON INSERT TO #{child_view} DO INSTEAD (
298
- SELECT setval('#{parent_pk_seq}', NEW.#{parent_pk});
299
298
  INSERT INTO #{parent_table}
300
299
  ( #{ [parent_pk, parent_columns].flatten.join(", ") } )
301
- VALUES( currval('#{parent_pk_seq}') #{ parent_columns.empty? ? '' : ',' + parent_columns.collect{ |col| "NEW." + col}.join(",") } )
302
- #{insert_returning_clause(child_view, parent_columns.unshift(parent_pk)) if supports_insert_with_returning?};
300
+ VALUES( DEFAULT #{ parent_columns.empty? ? '' : ' ,' + parent_columns.collect{ |col| "NEW." + col}.join(", ") } ) ;
303
301
  INSERT INTO #{child_table}
304
302
  ( #{ [child_pk, child_columns].flatten.join(",")} )
305
- VALUES( currval('#{parent_pk_seq}') #{ child_columns.empty? ? '' : ',' + child_columns.collect{ |col| "NEW." + col}.join(",") } )
303
+ VALUES( currval('#{parent_pk_seq}') #{ child_columns.empty? ? '' : ' ,' + child_columns.collect{ |col| "NEW." + col}.join(", ") } )
304
+ #{insert_returning_clause(parent_pk, child_pk, child_view) if supports_insert_with_returning?}
306
305
  )
307
306
  end_sql
308
307
 
@@ -330,15 +329,12 @@ module ActiveRecord #:nodoc:
330
329
  end_sql
331
330
  end
332
331
 
333
- def insert_returning_clause(child_view,parent_columns)
334
- "RETURNING "+
335
- columns(child_view).map do |c|
336
- if parent_columns.include?(c.name)
337
- c.name
338
- else
339
- "CAST (NULL AS #{c.sql_type})"
340
- end
341
- end.join(",")
332
+ def insert_returning_clause(parent_pk, child_pk, child_view)
333
+ columns_cast_to_null = columns(child_view)
334
+ .reject { |c| c.name == parent_pk}
335
+ .map { |c| "CAST (NULL AS #{c.sql_type})" }
336
+ .join(", ")
337
+ "RETURNING #{child_pk}, #{columns_cast_to_null}"
342
338
  end
343
339
 
344
340
  # Set default values from the table columns for a view
@@ -1,3 +1,3 @@
1
1
  module UpdateableViewsInheritance
2
- VERSION = "1.2.1"
2
+ VERSION = "1.2.2"
3
3
  end
data/test/content_test.rb CHANGED
@@ -3,9 +3,6 @@ require File.join(File.dirname(__FILE__), 'test_helper')
3
3
  class UpdateableViewsInheritanceContentTest < ActiveSupport::TestCase
4
4
  def setup
5
5
  ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 5)
6
- # order of fixtures is important for the test - last loaded should not be with max(id)
7
- ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', :electric_locomotives)
8
- ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', :steam_locomotives)
9
6
  end
10
7
 
11
8
  def teardown
@@ -13,6 +10,7 @@ class UpdateableViewsInheritanceContentTest < ActiveSupport::TestCase
13
10
  end
14
11
 
15
12
  def test_find
13
+ ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', :steam_locomotives)
16
14
  locomotive = Locomotive.find(1)
17
15
  assert locomotive.kind_of?(SteamLocomotive)
18
16
  assert_equal %w(coal_consumption id max_speed name type water_consumption),
@@ -20,8 +18,31 @@ class UpdateableViewsInheritanceContentTest < ActiveSupport::TestCase
20
18
  end
21
19
 
22
20
  def test_exec_query
23
- res = ActiveRecord::Base.connection.exec_query(%q{INSERT INTO electric_locomotives (electricity_consumption, max_speed, name, type) VALUES (40, 120, 'test', 'ElectricLocomotive') RETURNING id})
24
- assert !res.rows.empty?
21
+ # order of fixtures is important for the test - last loaded should not be with max(id)
22
+ ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', :electric_locomotives)
23
+ ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', :steam_locomotives)
24
+
25
+ res = ActiveRecord::Base.connection.exec_query(<<-SQL)
26
+ INSERT INTO electric_locomotives (electricity_consumption, max_speed, name, type)
27
+ VALUES (40, 120, 'BoBo', 'ElectricLocomotive') RETURNING id
28
+ SQL
29
+ assert !res.rows.empty?, 'No id returned on INSERT in database view'
30
+ assert_equal 3, res.rows.first.first.to_i
31
+ end
32
+
33
+ def test_exec_query_with_prepared_statement
34
+ # order of fixtures is important for the test - last loaded should not be with max(id)
35
+ ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', :electric_locomotives)
36
+ ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', :steam_locomotives)
37
+
38
+ binds = [[ElectricLocomotive.columns.find { |c| c.name == 'electricity_consumption'}, 40],
39
+ [ElectricLocomotive.columns.find { |c| c.name == 'max_speed'}, 120],
40
+ [ElectricLocomotive.columns.find { |c| c.name == 'name'}, 'BoBo'],
41
+ [ElectricLocomotive.columns.find { |c| c.name == 'type'}, 'ElectricLocomotive']]
42
+ res = ActiveRecord::Base.connection.exec_query(<<-SQL, 'Test prepared statement', binds)
43
+ INSERT INTO electric_locomotives (electricity_consumption, max_speed, name, type) VALUES ($1, $2, $3, $4) RETURNING id
44
+ SQL
45
+ assert !res.rows.empty?, 'Empty result on INSERT in database view through a prepared statement'
25
46
  assert_equal 3, res.rows.first.first.to_i
26
47
  end
27
48
 
@@ -32,6 +53,9 @@ class UpdateableViewsInheritanceContentTest < ActiveSupport::TestCase
32
53
  end
33
54
 
34
55
  def test_reset_sequence_after_loading_fixture
56
+ # order of fixtures is important for the test - last loaded should not be with max(id)
57
+ ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', :electric_locomotives)
58
+ ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', :steam_locomotives)
35
59
  steam_locomotive = SteamLocomotive.new(:name => 'Mogul', :max_speed => 120, :water_consumption => 12.3, :coal_consumption => 54.6)
36
60
  assert steam_locomotive.save
37
61
  mogul = Locomotive.find(steam_locomotive.id)
@@ -39,6 +63,7 @@ class UpdateableViewsInheritanceContentTest < ActiveSupport::TestCase
39
63
  end
40
64
 
41
65
  def test_update
66
+ ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', :steam_locomotives)
42
67
  steam_locomotive = Locomotive.find(1)
43
68
  steam_locomotive.update_attributes( :name => 'Rocket')
44
69
  steam_locomotive.reload
@@ -46,6 +71,7 @@ class UpdateableViewsInheritanceContentTest < ActiveSupport::TestCase
46
71
  end
47
72
 
48
73
  def test_delete_from_parent_relation
74
+ ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', :steam_locomotives)
49
75
  num_locomotives = Locomotive.count
50
76
  num_steam_locomotives = SteamLocomotive.count
51
77
  Locomotive.find(1).destroy
@@ -54,13 +80,11 @@ class UpdateableViewsInheritanceContentTest < ActiveSupport::TestCase
54
80
  end
55
81
 
56
82
  def test_delete_from_child_relation
83
+ ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', :steam_locomotives)
57
84
  num_locomotives = Locomotive.count
58
85
  num_steam_locomotives = SteamLocomotive.count
59
86
  SteamLocomotive.find(1).destroy
60
87
  assert_equal num_locomotives - 1, Locomotive.count
61
88
  assert_equal num_steam_locomotives - 1, SteamLocomotive.count
62
89
  end
63
-
64
-
65
-
66
90
  end
@@ -1,7 +1,4 @@
1
1
  test:
2
2
  adapter: postgresql
3
- username: postgres
4
- password: postgres
5
3
  database: updateable_views_inheritance_test
6
4
  min_messages: ERROR
7
- prepared_statements: false
@@ -0,0 +1,58 @@
1
+ gem "pg", "0.18.2"
2
+
3
+ require "pg"
4
+ require "rspec"
5
+
6
+ describe "Insert returning on view with rules and default value" do
7
+ before(:each) do
8
+ @conn = PG.connect(dbname: 'updateable_views_inheritance_test')
9
+ @conn.exec(%q{ SET client_min_messages TO 'ERROR' })
10
+
11
+ @conn.exec(%q{ CREATE TABLE parent ( id SERIAL PRIMARY KEY,
12
+ name TEXT) })
13
+ @conn.exec(%q{ CREATE TABLE child ( parent_id INTEGER PRIMARY KEY REFERENCES parent(id),
14
+ surname TEXT) })
15
+
16
+ @conn.exec(%q{ CREATE VIEW v AS (SELECT id, name, surname FROM parent JOIN child ON parent.id=child.parent_id) })
17
+ @conn.exec(%q{ ALTER VIEW v ALTER id SET DEFAULT nextval('parent_id_seq'::regclass) })
18
+ #
19
+ # The old way that didn't return anything when binds are empty
20
+ #
21
+ # @conn.exec(%q{ CREATE RULE v_on_insert AS ON INSERT TO v DO INSTEAD
22
+ # (
23
+ # SELECT setval('parent_id_seq', NEW.id);
24
+ # INSERT INTO parent (id, name)
25
+ # VALUES( currval('parent_id_seq'), NEW.name ) RETURNING id, name, NULL::text;
26
+ # INSERT INTO child (parent_id, surname)
27
+ # VALUES( currval('parent_id_seq'), NEW.surname );
28
+ #
29
+ # )
30
+ # })
31
+ @conn.exec(%q{ CREATE RULE v_on_insert AS ON INSERT TO v DO INSTEAD
32
+ (
33
+ INSERT INTO parent (id, name)
34
+ VALUES( DEFAULT, NEW.name );
35
+ INSERT INTO child (parent_id, surname)
36
+ VALUES( currval('parent_id_seq'), NEW.surname ) RETURNING parent_id, NULL::text, NULL::te;
37
+ )
38
+ })
39
+
40
+ @sql = %q{ INSERT INTO v (name, surname) VALUES ('parent', 'child') RETURNING id}
41
+ end
42
+
43
+ after(:each) do
44
+ @conn.exec(%q{ DROP VIEW IF EXISTS v })
45
+ @conn.exec(%q{ DROP TABLE IF EXISTS parent CASCADE})
46
+ @conn.exec(%q{ DROP TABLE IF EXISTS child CASCADE})
47
+ end
48
+
49
+ it 'async exec with empty binds' do
50
+ res = @conn.async_exec(@sql, [])
51
+ expect(res.values).to eq([["1"]])
52
+ end
53
+
54
+ it 'async exec with no binds' do
55
+ res = @conn.async_exec(@sql)
56
+ expect(res.values).to eq([["1"]])
57
+ end
58
+ end
data/test/test_helper.rb CHANGED
@@ -6,7 +6,11 @@ require 'rails/test_help'
6
6
  require 'updateable_views_inheritance'
7
7
 
8
8
  begin
9
- require 'ruby-debug'
9
+ if RUBY_VERSION > "2"
10
+ require 'byebug'
11
+ else
12
+ require 'debugger'
13
+ end
10
14
  rescue LoadError
11
15
  # no debugger available
12
16
  end
metadata CHANGED
@@ -1,7 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: updateable_views_inheritance
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.2.2
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Sava Chankov
@@ -9,11 +10,12 @@ authors:
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2014-08-27 00:00:00.000000000 Z
13
+ date: 2015-08-18 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: activerecord
16
17
  requirement: !ruby/object:Gem::Requirement
18
+ none: false
17
19
  requirements:
18
20
  - - ~>
19
21
  - !ruby/object:Gem::Version
@@ -21,6 +23,7 @@ dependencies:
21
23
  type: :runtime
22
24
  prerelease: false
23
25
  version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
24
27
  requirements:
25
28
  - - ~>
26
29
  - !ruby/object:Gem::Version
@@ -28,6 +31,7 @@ dependencies:
28
31
  - !ruby/object:Gem::Dependency
29
32
  name: pg
30
33
  requirement: !ruby/object:Gem::Requirement
34
+ none: false
31
35
  requirements:
32
36
  - - ! '>='
33
37
  - !ruby/object:Gem::Version
@@ -35,6 +39,7 @@ dependencies:
35
39
  type: :runtime
36
40
  prerelease: false
37
41
  version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
38
43
  requirements:
39
44
  - - ! '>='
40
45
  - !ruby/object:Gem::Version
@@ -42,6 +47,7 @@ dependencies:
42
47
  - !ruby/object:Gem::Dependency
43
48
  name: rails
44
49
  requirement: !ruby/object:Gem::Requirement
50
+ none: false
45
51
  requirements:
46
52
  - - ~>
47
53
  - !ruby/object:Gem::Version
@@ -49,6 +55,7 @@ dependencies:
49
55
  type: :development
50
56
  prerelease: false
51
57
  version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
52
59
  requirements:
53
60
  - - ~>
54
61
  - !ruby/object:Gem::Version
@@ -56,6 +63,7 @@ dependencies:
56
63
  - !ruby/object:Gem::Dependency
57
64
  name: bundler
58
65
  requirement: !ruby/object:Gem::Requirement
66
+ none: false
59
67
  requirements:
60
68
  - - ~>
61
69
  - !ruby/object:Gem::Version
@@ -63,6 +71,7 @@ dependencies:
63
71
  type: :development
64
72
  prerelease: false
65
73
  version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
66
75
  requirements:
67
76
  - - ~>
68
77
  - !ruby/object:Gem::Version
@@ -70,6 +79,7 @@ dependencies:
70
79
  - !ruby/object:Gem::Dependency
71
80
  name: rake
72
81
  requirement: !ruby/object:Gem::Requirement
82
+ none: false
73
83
  requirements:
74
84
  - - ! '>='
75
85
  - !ruby/object:Gem::Version
@@ -77,6 +87,7 @@ dependencies:
77
87
  type: :development
78
88
  prerelease: false
79
89
  version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
80
91
  requirements:
81
92
  - - ! '>='
82
93
  - !ruby/object:Gem::Version
@@ -104,10 +115,6 @@ files:
104
115
  - lib/updateable_views_inheritance/postgresql_adapter.rb
105
116
  - lib/updateable_views_inheritance/version.rb
106
117
  - tasks/updateable_views_inheritance_tasks.rake
107
- - test/config/database.yml
108
- - test/config/environment.rb
109
- - test/config/routes.rb
110
- - test/config/schema.rb
111
118
  - test/content_test.rb
112
119
  - test/deep_hierarchy_test.rb
113
120
  - test/dummy/Rakefile
@@ -176,6 +183,7 @@ files:
176
183
  - test/fixtures/steam_trains.yml
177
184
  - test/install_generator_test.rb
178
185
  - test/migration_test.rb
186
+ - test/pg_insert_returning_with_rules_spec.rb
179
187
  - test/schema_test.rb
180
188
  - test/single_table_inheritance.rb
181
189
  - test/test_helper.rb
@@ -183,32 +191,29 @@ files:
183
191
  homepage: http://github.com/tutuf/updateable_views_inheritance
184
192
  licenses:
185
193
  - MIT
186
- metadata: {}
187
194
  post_install_message:
188
195
  rdoc_options: []
189
196
  require_paths:
190
197
  - lib
191
198
  required_ruby_version: !ruby/object:Gem::Requirement
199
+ none: false
192
200
  requirements:
193
201
  - - ! '>='
194
202
  - !ruby/object:Gem::Version
195
203
  version: '0'
196
204
  required_rubygems_version: !ruby/object:Gem::Requirement
205
+ none: false
197
206
  requirements:
198
207
  - - ! '>='
199
208
  - !ruby/object:Gem::Version
200
209
  version: '0'
201
210
  requirements: []
202
211
  rubyforge_project:
203
- rubygems_version: 2.4.1
212
+ rubygems_version: 1.8.23
204
213
  signing_key:
205
- specification_version: 4
214
+ specification_version: 3
206
215
  summary: Class table inheritance for ActiveRecord
207
216
  test_files:
208
- - test/config/database.yml
209
- - test/config/environment.rb
210
- - test/config/routes.rb
211
- - test/config/schema.rb
212
217
  - test/content_test.rb
213
218
  - test/deep_hierarchy_test.rb
214
219
  - test/dummy/Rakefile
@@ -277,6 +282,7 @@ test_files:
277
282
  - test/fixtures/steam_trains.yml
278
283
  - test/install_generator_test.rb
279
284
  - test/migration_test.rb
285
+ - test/pg_insert_returning_with_rules_spec.rb
280
286
  - test/schema_test.rb
281
287
  - test/single_table_inheritance.rb
282
288
  - test/test_helper.rb
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MDFhNTFiOTNiNDBhYjg4MzY5NTBmMWQ1MjYyMWU1MGQyMTE0OTJmYw==
5
- data.tar.gz: !binary |-
6
- Y2I1NDc5YTAwNzVlMTdkODNjNjYwMmFlMjAxZDQ5MDk2ZDI4MWJkNg==
7
- SHA512:
8
- metadata.gz: !binary |-
9
- YzMxMjM3Y2I5MGJmMzBiN2ZjNGNiMzllOGYwMjA2ZDg0MjFlM2YxYmEzMzc5
10
- OTU5M2Y5ZmUxMDJhOTUxN2NjNTlhZWNjNjU4NWUzOGM0YzgxMDg5NDRjN2Zj
11
- OGJjNjYzMzlmOTVlYjlmMTMwOTRiOTZmMTJkZmY1OWViODAzZTQ=
12
- data.tar.gz: !binary |-
13
- YmU5NzU4ODA5YjNiYmU3NjE1MzdjODc1NTllM2IyMDk5NDFhNDVlM2EwNDQz
14
- ZTdmZGUzMDkxZGU1OTEwNWFiMGNjOTE1NGM1NDcwNGIyOTJlNGRjZGZkMzg4
15
- ZmY1Njk1YmM4MDg1ODRiODNjOTY4NmJjZWZhMjVkMDdjODJiNGQ=
@@ -1,19 +0,0 @@
1
- test:
2
- adapter: sqlite3
3
- dbfile: test.sqlite3.db
4
-
5
- # adapter: sqlite
6
- # dbfile: test.sqlite.db
7
-
8
- # adapter: mysql
9
- # host: localhost
10
- # username:
11
- # password:
12
- # database: test
13
-
14
- # adapter: postgresql
15
- # host: localhost
16
- # username:
17
- # password:
18
- # database: test
19
-
@@ -1,14 +0,0 @@
1
-
2
- Rails::Initializer.run do |config|
3
-
4
- config.cache_classes = true
5
-
6
- config.whiny_nils = true
7
-
8
- config.action_controller.consider_all_requests_local = true
9
- config.action_controller.perform_caching = false
10
-
11
- config.action_mailer.delivery_method = :test
12
- config.action_mailer.perform_deliveries = true
13
-
14
- end
@@ -1,3 +0,0 @@
1
- ActionController::Routing::Routes.draw do |map|
2
-
3
- end
@@ -1,3 +0,0 @@
1
- ActiveRecord::Schema.define(:version => 2) do
2
-
3
- end