schema_plus_views 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/lib/schema_plus/views/active_record/migration/command_recorder.rb +20 -0
- data/lib/schema_plus/views/version.rb +1 -1
- data/lib/schema_plus/views.rb +1 -0
- data/spec/dumper_spec.rb +78 -0
- data/spec/introspection_spec.rb +93 -0
- data/spec/migration_spec.rb +116 -0
- metadata +9 -4
- data/spec/views_spec.rb +0 -193
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2a5ea547ab99bca7ef7d039c784b580065ef142
|
4
|
+
data.tar.gz: b1dc65dab6140a1c68de87da4c2d6eb54620879b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5e60a51b299a09aa1429f1da508a217c9306bb7a126ad0f499849255b1d7942edac5b2b905e3c82abc4cc2aeb3fc261451882f8786b30d5c981004c6e199725
|
7
|
+
data.tar.gz: 01eb9ee07f00334652b549e81bd20a280ba6d9b0b5ac48d806d1eafe7dde63273817078566aa06245775f7a38322355884cb2e5296c1ceae857b09d56b2669fd
|
data/README.md
CHANGED
@@ -109,6 +109,7 @@ This returns just the body of the definition, i.e. the part after the `CREATE VI
|
|
109
109
|
|
110
110
|
## History
|
111
111
|
|
112
|
+
* 0.2.1 - Fix db:rollback
|
112
113
|
* 0.2.0 - Added :allow_replace option (thanks to [@hcarver](https://github.com/hcarver))
|
113
114
|
* 0.1.0 - Initial release, extracted from schema_plus 1.x
|
114
115
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SchemaPlus::Views
|
2
|
+
module ActiveRecord
|
3
|
+
module Migration
|
4
|
+
module CommandRecorder
|
5
|
+
def create_view(*args, &block)
|
6
|
+
record(:create_view, args, &block)
|
7
|
+
end
|
8
|
+
|
9
|
+
def drop_view(*args, &block)
|
10
|
+
record(:drop_view, args, &block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def invert_create_view(args)
|
14
|
+
[ :drop_view, [args.first] ]
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/schema_plus/views.rb
CHANGED
data/spec/dumper_spec.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Item < ActiveRecord::Base
|
4
|
+
end
|
5
|
+
|
6
|
+
describe "Dumper" do
|
7
|
+
|
8
|
+
let(:schema) { ActiveRecord::Schema }
|
9
|
+
|
10
|
+
let(:migration) { ActiveRecord::Migration }
|
11
|
+
|
12
|
+
let(:connection) { ActiveRecord::Base.connection }
|
13
|
+
|
14
|
+
before(:each) do
|
15
|
+
define_schema_and_data
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should include view definitions" do
|
19
|
+
expect(dump).to match(%r{create_view "a_ones", " ?SELECT .*b.*,.*s.* FROM .*items.* WHERE .*a.* = 1.*, :force => true}mi)
|
20
|
+
expect(dump).to match(%r{create_view "ab_ones", " ?SELECT .*s.* FROM .*a_ones.* WHERE .*b.* = 1.*, :force => true}mi)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should include views in dependency order" do
|
24
|
+
expect(dump).to match(%r{create_table "items".*create_view "a_ones".*create_view "ab_ones"}m)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should not include views listed in ignore_tables" do
|
28
|
+
dump(ignore_tables: /b_/) do |dump|
|
29
|
+
expect(dump).to match(%r{create_view "a_ones", " ?SELECT .*b.*,.*s.* FROM .*items.* WHERE .*a.* = 1.*, :force => true}mi)
|
30
|
+
expect(dump).not_to match(%r{"ab_ones"})
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should not reference current database" do
|
35
|
+
# why check this? mysql default to providing the view definition
|
36
|
+
# with tables explicitly scoped to the current database, which
|
37
|
+
# resulted in the dump being bound to the current database. this
|
38
|
+
# caused trouble for rails, in which creates the schema dump file
|
39
|
+
# when in the (say) development database, but then uses it to
|
40
|
+
# initialize the test database when testing. this meant that the
|
41
|
+
# test database had views into the development database.
|
42
|
+
db = connection.respond_to?(:current_database)? connection.current_database : SchemaDev::Rspec.db_configuration[:database]
|
43
|
+
expect(dump).not_to match(%r{#{connection.quote_table_name(db)}[.]})
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def define_schema_and_data
|
49
|
+
connection.views.each do |view| connection.drop_view view end
|
50
|
+
connection.tables.each do |table| connection.drop_table table, cascade: true end
|
51
|
+
|
52
|
+
schema.define do
|
53
|
+
|
54
|
+
create_table :items, :force => true do |t|
|
55
|
+
t.integer :a
|
56
|
+
t.integer :b
|
57
|
+
t.string :s
|
58
|
+
end
|
59
|
+
|
60
|
+
create_view :a_ones, Item.select('b, s').where(:a => 1)
|
61
|
+
create_view :ab_ones, "select s from a_ones where b = 1"
|
62
|
+
end
|
63
|
+
connection.execute "insert into items (a, b, s) values (1, 1, 'one_one')"
|
64
|
+
connection.execute "insert into items (a, b, s) values (1, 2, 'one_two')"
|
65
|
+
connection.execute "insert into items (a, b, s) values (2, 1, 'two_one')"
|
66
|
+
connection.execute "insert into items (a, b, s) values (2, 2, 'two_two')"
|
67
|
+
end
|
68
|
+
|
69
|
+
def dump(opts={})
|
70
|
+
StringIO.open { |stream|
|
71
|
+
ActiveRecord::SchemaDumper.ignore_tables = Array.wrap(opts[:ignore_tables])
|
72
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
73
|
+
yield stream.string if block_given?
|
74
|
+
stream.string
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Item < ActiveRecord::Base
|
4
|
+
end
|
5
|
+
|
6
|
+
describe "Introspection" do
|
7
|
+
|
8
|
+
let(:schema) { ActiveRecord::Schema }
|
9
|
+
|
10
|
+
let(:migration) { ActiveRecord::Migration }
|
11
|
+
|
12
|
+
let(:connection) { ActiveRecord::Base.connection }
|
13
|
+
|
14
|
+
before(:each) do
|
15
|
+
define_schema_and_data
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should list all views" do
|
19
|
+
expect(connection.views.sort).to eq(%W[a_ones ab_ones])
|
20
|
+
expect(connection.view_definition('a_ones')).to match(%r{^ ?SELECT .*b.*,.*s.* FROM .*items.* WHERE .*a.* = 1}mi)
|
21
|
+
expect(connection.view_definition('ab_ones')).to match(%r{^ ?SELECT .*s.* FROM .*a_ones.* WHERE .*b.* = 1}mi)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should ignore views named pg_*", postgresql: :only do
|
25
|
+
begin
|
26
|
+
migration.create_view :pg_dummy_internal, "select 1"
|
27
|
+
expect(connection.views.sort).to eq(%W[a_ones ab_ones])
|
28
|
+
ensure
|
29
|
+
migration.drop_view :pg_dummy_internal
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should not be listed as a table" do
|
34
|
+
expect(connection.tables).not_to include('a_ones')
|
35
|
+
expect(connection.tables).not_to include('ab_ones')
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should introspect definition" do
|
39
|
+
expect(connection.view_definition('a_ones')).to match(%r{^ ?SELECT .*b.*,.*s.* FROM .*items.* WHERE .*a.* = 1}mi)
|
40
|
+
expect(connection.view_definition('ab_ones')).to match(%r{^ ?SELECT .*s.* FROM .*a_ones.* WHERE .*b.* = 1}mi)
|
41
|
+
end
|
42
|
+
|
43
|
+
context "in mysql", :mysql => :only do
|
44
|
+
|
45
|
+
around(:each) do |example|
|
46
|
+
begin
|
47
|
+
migration.drop_view :check if connection.views.include? 'check'
|
48
|
+
example.run
|
49
|
+
ensure
|
50
|
+
migration.drop_view :check if connection.views.include? 'check'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should introspect WITH CHECK OPTION" do
|
55
|
+
migration.create_view :check, 'SELECT * FROM items WHERE (a=2) WITH CHECK OPTION'
|
56
|
+
expect(connection.view_definition('check')).to match(%r{WITH CASCADED CHECK OPTION$})
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should introspect WITH CASCADED CHECK OPTION" do
|
60
|
+
migration.create_view :check, 'SELECT * FROM items WHERE (a=2) WITH CASCADED CHECK OPTION'
|
61
|
+
expect(connection.view_definition('check')).to match(%r{WITH CASCADED CHECK OPTION$})
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should introspect WITH LOCAL CHECK OPTION" do
|
65
|
+
migration.create_view :check, 'SELECT * FROM items WHERE (a=2) WITH LOCAL CHECK OPTION'
|
66
|
+
expect(connection.view_definition('check')).to match(%r{WITH LOCAL CHECK OPTION$})
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
protected
|
71
|
+
|
72
|
+
def define_schema_and_data
|
73
|
+
connection.views.each do |view| connection.drop_view view end
|
74
|
+
connection.tables.each do |table| connection.drop_table table, cascade: true end
|
75
|
+
|
76
|
+
schema.define do
|
77
|
+
|
78
|
+
create_table :items, :force => true do |t|
|
79
|
+
t.integer :a
|
80
|
+
t.integer :b
|
81
|
+
t.string :s
|
82
|
+
end
|
83
|
+
|
84
|
+
create_view :a_ones, Item.select('b, s').where(:a => 1)
|
85
|
+
create_view :ab_ones, "select s from a_ones where b = 1"
|
86
|
+
end
|
87
|
+
connection.execute "insert into items (a, b, s) values (1, 1, 'one_one')"
|
88
|
+
connection.execute "insert into items (a, b, s) values (1, 2, 'one_two')"
|
89
|
+
connection.execute "insert into items (a, b, s) values (2, 1, 'two_one')"
|
90
|
+
connection.execute "insert into items (a, b, s) values (2, 2, 'two_two')"
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Item < ActiveRecord::Base
|
4
|
+
end
|
5
|
+
|
6
|
+
class AOnes < ActiveRecord::Base
|
7
|
+
end
|
8
|
+
|
9
|
+
class ABOnes < ActiveRecord::Base
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "Migration" do
|
13
|
+
|
14
|
+
let(:migration) { ActiveRecord::Migration }
|
15
|
+
let(:connection) { ActiveRecord::Base.connection }
|
16
|
+
let(:schema) { ActiveRecord::Schema }
|
17
|
+
|
18
|
+
before(:each) do
|
19
|
+
define_schema_and_data
|
20
|
+
end
|
21
|
+
|
22
|
+
context "creation" do
|
23
|
+
it "should create correct views" do
|
24
|
+
expect(AOnes.all.collect(&:s)).to eq(%W[one_one one_two])
|
25
|
+
expect(ABOnes.all.collect(&:s)).to eq(%W[one_one])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "duplicate creation" do
|
30
|
+
before(:each) do
|
31
|
+
migration.create_view('dupe_me', 'SELECT * FROM items WHERE (a=1)')
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should raise an error by default" do
|
35
|
+
expect {migration.create_view('dupe_me', 'SELECT * FROM items WHERE (a=2)')}.to raise_error ActiveRecord::StatementInvalid
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should override existing definition if :force true" do
|
39
|
+
migration.create_view('dupe_me', 'SELECT * FROM items WHERE (a=2)', :force => true)
|
40
|
+
expect(connection.view_definition('dupe_me')).to match(%r{WHERE .*a.*=.*2}i)
|
41
|
+
end
|
42
|
+
|
43
|
+
context "Postgres and MySQL only", :sqlite3 => :skip do
|
44
|
+
it "should override existing definition if :allow_replace is true" do
|
45
|
+
migration.create_view('dupe_me', 'SELECT * FROM items WHERE (a=2)', :allow_replace => true)
|
46
|
+
expect(connection.view_definition('dupe_me')).to match(%r{WHERE .*a.*=.*2}i)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "dropping" do
|
52
|
+
it "should raise an error if the view doesn't exist" do
|
53
|
+
expect { migration.drop_view('doesnt_exist') }.to raise_error ActiveRecord::StatementInvalid
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should fail silently when using if_exists option" do
|
57
|
+
expect { migration.drop_view('doesnt_exist', :if_exists => true) }.not_to raise_error
|
58
|
+
end
|
59
|
+
|
60
|
+
context "with a view that exists" do
|
61
|
+
before { migration.create_view('view_that_exists', 'SELECT * FROM items WHERE (a=1)') }
|
62
|
+
|
63
|
+
it "should succeed" do
|
64
|
+
migration.drop_view('view_that_exists')
|
65
|
+
expect(connection.views).not_to include('view_that_exists')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "rollback" do
|
71
|
+
it "properly rolls back a create_view" do
|
72
|
+
m = Class.new ::ActiveRecord::Migration do
|
73
|
+
define_method(:change) {
|
74
|
+
create_view :copy, "SELECT * FROM items"
|
75
|
+
}
|
76
|
+
end
|
77
|
+
m.migrate(:up)
|
78
|
+
expect(connection.views).to include("copy")
|
79
|
+
m.migrate(:down)
|
80
|
+
expect(connection.views).not_to include("copy")
|
81
|
+
end
|
82
|
+
|
83
|
+
it "raises error for drop_view" do
|
84
|
+
m = Class.new ::ActiveRecord::Migration do
|
85
|
+
define_method(:change) {
|
86
|
+
drop_view :a_ones
|
87
|
+
}
|
88
|
+
end
|
89
|
+
expect { m.migrate(:down) }.to raise_error(::ActiveRecord::IrreversibleMigration)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
protected
|
95
|
+
|
96
|
+
def define_schema_and_data
|
97
|
+
connection.views.each do |view| connection.drop_view view end
|
98
|
+
connection.tables.each do |table| connection.drop_table table, cascade: true end
|
99
|
+
|
100
|
+
schema.define do
|
101
|
+
|
102
|
+
create_table :items, :force => true do |t|
|
103
|
+
t.integer :a
|
104
|
+
t.integer :b
|
105
|
+
t.string :s
|
106
|
+
end
|
107
|
+
|
108
|
+
create_view :a_ones, Item.select('b, s').where(:a => 1)
|
109
|
+
create_view :ab_ones, "select s from a_ones where b = 1"
|
110
|
+
end
|
111
|
+
connection.execute "insert into items (a, b, s) values (1, 1, 'one_one')"
|
112
|
+
connection.execute "insert into items (a, b, s) values (1, 2, 'one_two')"
|
113
|
+
connection.execute "insert into items (a, b, s) values (2, 1, 'two_one')"
|
114
|
+
connection.execute "insert into items (a, b, s) values (2, 2, 'two_two')"
|
115
|
+
end
|
116
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schema_plus_views
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ronen barzel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -145,15 +145,18 @@ files:
|
|
145
145
|
- lib/schema_plus/views/active_record/connection_adapters/mysql2_adapter.rb
|
146
146
|
- lib/schema_plus/views/active_record/connection_adapters/postgresql_adapter.rb
|
147
147
|
- lib/schema_plus/views/active_record/connection_adapters/sqlite3_adapter.rb
|
148
|
+
- lib/schema_plus/views/active_record/migration/command_recorder.rb
|
148
149
|
- lib/schema_plus/views/middleware.rb
|
149
150
|
- lib/schema_plus/views/version.rb
|
150
151
|
- lib/schema_plus_views.rb
|
151
152
|
- schema_dev.yml
|
152
153
|
- schema_plus_views.gemspec
|
154
|
+
- spec/dumper_spec.rb
|
155
|
+
- spec/introspection_spec.rb
|
156
|
+
- spec/migration_spec.rb
|
153
157
|
- spec/named_schemas_spec.rb
|
154
158
|
- spec/sanity_spec.rb
|
155
159
|
- spec/spec_helper.rb
|
156
|
-
- spec/views_spec.rb
|
157
160
|
homepage: https://github.com/SchemaPlus/schema_plus_views
|
158
161
|
licenses:
|
159
162
|
- MIT
|
@@ -179,7 +182,9 @@ signing_key:
|
|
179
182
|
specification_version: 4
|
180
183
|
summary: Adds support for views to ActiveRecord
|
181
184
|
test_files:
|
185
|
+
- spec/dumper_spec.rb
|
186
|
+
- spec/introspection_spec.rb
|
187
|
+
- spec/migration_spec.rb
|
182
188
|
- spec/named_schemas_spec.rb
|
183
189
|
- spec/sanity_spec.rb
|
184
190
|
- spec/spec_helper.rb
|
185
|
-
- spec/views_spec.rb
|
data/spec/views_spec.rb
DELETED
@@ -1,193 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
class Item < ActiveRecord::Base
|
4
|
-
end
|
5
|
-
|
6
|
-
class AOnes < ActiveRecord::Base
|
7
|
-
end
|
8
|
-
|
9
|
-
class ABOnes < ActiveRecord::Base
|
10
|
-
end
|
11
|
-
|
12
|
-
describe "Views" do
|
13
|
-
|
14
|
-
let(:schema) { ActiveRecord::Schema }
|
15
|
-
|
16
|
-
let(:migration) { ActiveRecord::Migration }
|
17
|
-
|
18
|
-
let(:connection) { ActiveRecord::Base.connection }
|
19
|
-
|
20
|
-
before(:each) do
|
21
|
-
define_schema_and_data
|
22
|
-
end
|
23
|
-
|
24
|
-
context "querys" do
|
25
|
-
|
26
|
-
it "should query correctly" do
|
27
|
-
expect(AOnes.all.collect(&:s)).to eq(%W[one_one one_two])
|
28
|
-
expect(ABOnes.all.collect(&:s)).to eq(%W[one_one])
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
context "introspection" do
|
34
|
-
|
35
|
-
it "should list all views" do
|
36
|
-
expect(connection.views.sort).to eq(%W[a_ones ab_ones])
|
37
|
-
expect(connection.view_definition('a_ones')).to match(%r{^ ?SELECT .*b.*,.*s.* FROM .*items.* WHERE .*a.* = 1}mi)
|
38
|
-
expect(connection.view_definition('ab_ones')).to match(%r{^ ?SELECT .*s.* FROM .*a_ones.* WHERE .*b.* = 1}mi)
|
39
|
-
end
|
40
|
-
|
41
|
-
it "should ignore views named pg_*", postgresql: :only do
|
42
|
-
begin
|
43
|
-
migration.create_view :pg_dummy_internal, "select 1"
|
44
|
-
expect(connection.views.sort).to eq(%W[a_ones ab_ones])
|
45
|
-
ensure
|
46
|
-
migration.drop_view :pg_dummy_internal
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
it "should not be listed as a table" do
|
51
|
-
expect(connection.tables).not_to include('a_ones')
|
52
|
-
expect(connection.tables).not_to include('ab_ones')
|
53
|
-
end
|
54
|
-
|
55
|
-
it "should introspect definition" do
|
56
|
-
expect(connection.view_definition('a_ones')).to match(%r{^ ?SELECT .*b.*,.*s.* FROM .*items.* WHERE .*a.* = 1}mi)
|
57
|
-
expect(connection.view_definition('ab_ones')).to match(%r{^ ?SELECT .*s.* FROM .*a_ones.* WHERE .*b.* = 1}mi)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
|
62
|
-
context "dumper" do
|
63
|
-
|
64
|
-
it "should include view definitions" do
|
65
|
-
expect(dump).to match(%r{create_view "a_ones", " ?SELECT .*b.*,.*s.* FROM .*items.* WHERE .*a.* = 1.*, :force => true}mi)
|
66
|
-
expect(dump).to match(%r{create_view "ab_ones", " ?SELECT .*s.* FROM .*a_ones.* WHERE .*b.* = 1.*, :force => true}mi)
|
67
|
-
end
|
68
|
-
|
69
|
-
it "should include views in dependency order" do
|
70
|
-
expect(dump).to match(%r{create_table "items".*create_view "a_ones".*create_view "ab_ones"}m)
|
71
|
-
end
|
72
|
-
|
73
|
-
it "should not include views listed in ignore_tables" do
|
74
|
-
dump(ignore_tables: /b_/) do |dump|
|
75
|
-
expect(dump).to match(%r{create_view "a_ones", " ?SELECT .*b.*,.*s.* FROM .*items.* WHERE .*a.* = 1.*, :force => true}mi)
|
76
|
-
expect(dump).not_to match(%r{"ab_ones"})
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should not reference current database" do
|
81
|
-
# why check this? mysql default to providing the view definition
|
82
|
-
# with tables explicitly scoped to the current database, which
|
83
|
-
# resulted in the dump being bound to the current database. this
|
84
|
-
# caused trouble for rails, in which creates the schema dump file
|
85
|
-
# when in the (say) development database, but then uses it to
|
86
|
-
# initialize the test database when testing. this meant that the
|
87
|
-
# test database had views into the development database.
|
88
|
-
db = connection.respond_to?(:current_database)? connection.current_database : SchemaDev::Rspec.db_configuration[:database]
|
89
|
-
expect(dump).not_to match(%r{#{connection.quote_table_name(db)}[.]})
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
context "duplicate creation" do
|
94
|
-
before(:each) do
|
95
|
-
migration.create_view('dupe_me', 'SELECT * FROM items WHERE (a=1)')
|
96
|
-
end
|
97
|
-
|
98
|
-
it "should raise an error by default" do
|
99
|
-
expect {migration.create_view('dupe_me', 'SELECT * FROM items WHERE (a=2)')}.to raise_error ActiveRecord::StatementInvalid
|
100
|
-
end
|
101
|
-
|
102
|
-
it "should override existing definition if :force true" do
|
103
|
-
migration.create_view('dupe_me', 'SELECT * FROM items WHERE (a=2)', :force => true)
|
104
|
-
expect(connection.view_definition('dupe_me')).to match(%r{WHERE .*a.*=.*2}i)
|
105
|
-
end
|
106
|
-
|
107
|
-
context "Postgres and MySQL only", :sqlite3 => :skip do
|
108
|
-
it "should override existing definition if :allow_replace is true" do
|
109
|
-
migration.create_view('dupe_me', 'SELECT * FROM items WHERE (a=2)', :allow_replace => true)
|
110
|
-
expect(connection.view_definition('dupe_me')).to match(%r{WHERE .*a.*=.*2}i)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
context "dropping" do
|
116
|
-
it "should raise an error if the view doesn't exist" do
|
117
|
-
expect { migration.drop_view('doesnt_exist') }.to raise_error ActiveRecord::StatementInvalid
|
118
|
-
end
|
119
|
-
|
120
|
-
it "should fail silently when using if_exists option" do
|
121
|
-
expect { migration.drop_view('doesnt_exist', :if_exists => true) }.not_to raise_error
|
122
|
-
end
|
123
|
-
|
124
|
-
context "with a view that exists" do
|
125
|
-
before { migration.create_view('view_that_exists', 'SELECT * FROM items WHERE (a=1)') }
|
126
|
-
|
127
|
-
it "should succeed" do
|
128
|
-
migration.drop_view('view_that_exists')
|
129
|
-
expect(connection.views).not_to include('view_that_exists')
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
context "in mysql", :mysql => :only do
|
135
|
-
|
136
|
-
around(:each) do |example|
|
137
|
-
begin
|
138
|
-
migration.drop_view :check if connection.views.include? 'check'
|
139
|
-
example.run
|
140
|
-
ensure
|
141
|
-
migration.drop_view :check if connection.views.include? 'check'
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
it "should introspect WITH CHECK OPTION" do
|
146
|
-
migration.create_view :check, 'SELECT * FROM items WHERE (a=2) WITH CHECK OPTION'
|
147
|
-
expect(connection.view_definition('check')).to match(%r{WITH CASCADED CHECK OPTION$})
|
148
|
-
end
|
149
|
-
|
150
|
-
it "should introspect WITH CASCADED CHECK OPTION" do
|
151
|
-
migration.create_view :check, 'SELECT * FROM items WHERE (a=2) WITH CASCADED CHECK OPTION'
|
152
|
-
expect(connection.view_definition('check')).to match(%r{WITH CASCADED CHECK OPTION$})
|
153
|
-
end
|
154
|
-
|
155
|
-
it "should introspect WITH LOCAL CHECK OPTION" do
|
156
|
-
migration.create_view :check, 'SELECT * FROM items WHERE (a=2) WITH LOCAL CHECK OPTION'
|
157
|
-
expect(connection.view_definition('check')).to match(%r{WITH LOCAL CHECK OPTION$})
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
protected
|
162
|
-
|
163
|
-
def define_schema_and_data
|
164
|
-
connection.views.each do |view| connection.drop_view view end
|
165
|
-
connection.tables.each do |table| connection.drop_table table, cascade: true end
|
166
|
-
|
167
|
-
schema.define do
|
168
|
-
|
169
|
-
create_table :items, :force => true do |t|
|
170
|
-
t.integer :a
|
171
|
-
t.integer :b
|
172
|
-
t.string :s
|
173
|
-
end
|
174
|
-
|
175
|
-
create_view :a_ones, Item.select('b, s').where(:a => 1)
|
176
|
-
create_view :ab_ones, "select s from a_ones where b = 1"
|
177
|
-
end
|
178
|
-
connection.execute "insert into items (a, b, s) values (1, 1, 'one_one')"
|
179
|
-
connection.execute "insert into items (a, b, s) values (1, 2, 'one_two')"
|
180
|
-
connection.execute "insert into items (a, b, s) values (2, 1, 'two_one')"
|
181
|
-
connection.execute "insert into items (a, b, s) values (2, 2, 'two_two')"
|
182
|
-
end
|
183
|
-
|
184
|
-
def dump(opts={})
|
185
|
-
StringIO.open { |stream|
|
186
|
-
ActiveRecord::SchemaDumper.ignore_tables = Array.wrap(opts[:ignore_tables])
|
187
|
-
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
188
|
-
yield stream.string if block_given?
|
189
|
-
stream.string
|
190
|
-
}
|
191
|
-
end
|
192
|
-
|
193
|
-
end
|