schema_plus 2.0.0.pre3 → 2.0.0.pre5

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -1
  3. data/README.md +4 -28
  4. data/TODO.md +5 -2
  5. data/gemfiles/Gemfile.base +0 -4
  6. data/lib/schema_plus.rb +1 -1
  7. data/lib/schema_plus/version.rb +1 -1
  8. data/lib/schema_plus_db_default.rb +0 -6
  9. data/lib/schema_plus_db_default/active_record/attribute.rb +2 -5
  10. data/lib/schema_plus_db_default/db_default.rb +2 -0
  11. data/lib/schema_plus_db_default/middleware.rb +1 -1
  12. data/lib/schema_plus_default_expr.rb +1 -0
  13. data/lib/schema_plus_default_expr/active_record/connection_adapters/column.rb +14 -0
  14. data/lib/schema_plus_default_expr/active_record/connection_adapters/sqlite3_adapter.rb +0 -16
  15. data/lib/schema_plus_default_expr/middleware.rb +3 -4
  16. data/lib/schema_plus_enums/middleware.rb +2 -2
  17. data/lib/schema_plus_foreign_keys.rb +1 -5
  18. data/lib/schema_plus_foreign_keys/active_record/base.rb +0 -4
  19. data/lib/schema_plus_foreign_keys/active_record/connection_adapters/abstract_adapter.rb +13 -19
  20. data/lib/schema_plus_foreign_keys/active_record/connection_adapters/foreign_key_definition.rb +9 -15
  21. data/lib/schema_plus_foreign_keys/active_record/connection_adapters/mysql2_adapter.rb +4 -12
  22. data/lib/schema_plus_foreign_keys/active_record/connection_adapters/postgresql_adapter.rb +2 -8
  23. data/lib/schema_plus_foreign_keys/active_record/connection_adapters/sqlite3_adapter.rb +2 -8
  24. data/lib/schema_plus_foreign_keys/active_record/migration/command_recorder.rb +3 -9
  25. data/lib/schema_plus_foreign_keys/active_record/schema.rb +3 -12
  26. data/lib/schema_plus_foreign_keys/middleware/dumper.rb +1 -1
  27. data/lib/schema_plus_foreign_keys/middleware/sql.rb +11 -0
  28. data/schema_dev.yml +0 -1
  29. data/schema_plus.gemspec +29 -28
  30. data/spec/schema_plus_foreign_keys/foreign_key_spec.rb +0 -22
  31. metadata +38 -27
  32. data/lib/schema_plus_foreign_keys/active_record/connection_adapters/schema_statements.rb +0 -33
  33. data/lib/schema_plus_views.rb +0 -16
  34. data/lib/schema_plus_views/active_record/connection_adapters/abstract_adapter.rb +0 -41
  35. data/lib/schema_plus_views/active_record/connection_adapters/mysql2_adapter.rb +0 -30
  36. data/lib/schema_plus_views/active_record/connection_adapters/postgresql_adapter.rb +0 -31
  37. data/lib/schema_plus_views/active_record/connection_adapters/sqlite3_adapter.rb +0 -18
  38. data/lib/schema_plus_views/middleware.rb +0 -49
  39. data/spec/schema_plus_views/named_schemas_spec.rb +0 -97
  40. data/spec/schema_plus_views/views_spec.rb +0 -194
@@ -1,16 +0,0 @@
1
- require 'schema_monkey'
2
-
3
- require_relative 'schema_plus_views/active_record/connection_adapters/abstract_adapter'
4
- require_relative 'schema_plus_views/middleware'
5
-
6
- module SchemaPlusViews
7
- module ActiveRecord
8
- module ConnectionAdapters
9
- autoload :Mysql2Adapter, 'schema_plus_views/active_record/connection_adapters/mysql2_adapter'
10
- autoload :PostgresqlAdapter, 'schema_plus_views/active_record/connection_adapters/postgresql_adapter'
11
- autoload :Sqlite3Adapter, 'schema_plus_views/active_record/connection_adapters/sqlite3_adapter'
12
- end
13
- end
14
- end
15
-
16
- SchemaMonkey.register(SchemaPlusViews)
@@ -1,41 +0,0 @@
1
- module SchemaPlusViews
2
- module ActiveRecord
3
- module ConnectionAdapters
4
- module AbstractAdapter
5
- # Create a view given the SQL definition. Specify :force => true
6
- # to first drop the view if it already exists.
7
- def create_view(view_name, definition, options={})
8
- definition = definition.to_sql if definition.respond_to? :to_sql
9
- if options[:force]
10
- drop_view(view_name, if_exists: true)
11
- end
12
- execute "CREATE VIEW #{quote_table_name(view_name)} AS #{definition}"
13
- end
14
-
15
- # Drop the named view. Specify :if_exists => true
16
- # to fail silently if the view doesn't exist.
17
- def drop_view(view_name, options = {})
18
- sql = "DROP VIEW"
19
- sql += " IF EXISTS" if options[:if_exists]
20
- sql += " #{quote_table_name(view_name)}"
21
- execute sql
22
- end
23
-
24
- #####################################################################
25
- #
26
- # The functions below here are abstract; each subclass should
27
- # define them all. Defining them here only for reference.
28
- #
29
-
30
- # (abstract) Returns the names of all views, as an array of strings
31
- def views(name = nil) raise "Internal Error: Connection adapter didn't override abstract function"; [] end
32
-
33
- # (abstract) Returns the SQL definition of a given view. This is
34
- # the literal SQL would come after 'CREATVE VIEW viewname AS ' in
35
- # the SQL statement to create a view.
36
- def view_definition(view_name, name = nil) raise "Internal Error: Connection adapter didn't override abstract function"; end
37
- end
38
- end
39
- end
40
- end
41
-
@@ -1,30 +0,0 @@
1
- module SchemaPlusViews
2
- module ActiveRecord
3
- module ConnectionAdapters
4
- module Mysql2Adapter
5
-
6
- def views(name = nil)
7
- views = []
8
- select_all("SELECT table_name FROM information_schema.views WHERE table_schema = SCHEMA()", name).each do |row|
9
- views << row["table_name"]
10
- end
11
- views
12
- end
13
-
14
- def view_definition(view_name, name = nil)
15
- results = select_all("SELECT view_definition, check_option FROM information_schema.views WHERE table_schema = SCHEMA() AND table_name = #{quote(view_name)}", name)
16
- return nil unless results.any?
17
- row = results.first
18
- sql = row["view_definition"]
19
- sql.gsub!(%r{#{quote_table_name(current_database)}[.]}, '')
20
- case row["check_option"]
21
- when "CASCADED" then sql += " WITH CASCADED CHECK OPTION"
22
- when "LOCAL" then sql += " WITH LOCAL CHECK OPTION"
23
- end
24
- sql
25
- end
26
-
27
- end
28
- end
29
- end
30
- end
@@ -1,31 +0,0 @@
1
- module SchemaPlusViews
2
- module ActiveRecord
3
- module ConnectionAdapters
4
- module PostgresqlAdapter
5
-
6
- def views(name = nil) #:nodoc:
7
- sql = <<-SQL
8
- SELECT viewname
9
- FROM pg_views
10
- WHERE schemaname = ANY (current_schemas(false))
11
- AND viewname NOT LIKE 'pg\_%'
12
- SQL
13
- sql += " AND schemaname != 'postgis'" if adapter_name == 'PostGIS'
14
- query(sql, name).map { |row| row[0] }
15
- end
16
-
17
- def view_definition(view_name, name = nil) #:nodoc:
18
- result = query(<<-SQL, name)
19
- SELECT pg_get_viewdef(oid)
20
- FROM pg_class
21
- WHERE relkind = 'v'
22
- AND relname = '#{view_name}'
23
- SQL
24
- row = result.first
25
- row.first.chomp(';') unless row.nil?
26
- end
27
-
28
- end
29
- end
30
- end
31
- end
@@ -1,18 +0,0 @@
1
- module SchemaPlusViews
2
- module ActiveRecord
3
- module ConnectionAdapters
4
- module Sqlite3Adapter
5
-
6
- def views(name = nil)
7
- execute("SELECT name FROM sqlite_master WHERE type='view'", name).collect{|row| row["name"]}
8
- end
9
-
10
- def view_definition(view_name, name = nil)
11
- sql = execute("SELECT sql FROM sqlite_master WHERE type='view' AND name=#{quote(view_name)}", name).collect{|row| row["sql"]}.first
12
- sql.sub(/^CREATE VIEW \S* AS\s+/im, '') unless sql.nil?
13
- end
14
-
15
- end
16
- end
17
- end
18
- end
@@ -1,49 +0,0 @@
1
- module SchemaPlusViews
2
- module Middleware
3
-
4
- module Dumper
5
- module Tables
6
-
7
- # Dump views
8
- def after(env)
9
- re_view_referent = %r{(?:(?i)FROM|JOIN) \S*\b(\S+)\b}
10
- env.connection.views.each do |view_name|
11
- next if env.dumper.ignored?(view_name)
12
- view = View.new(name: view_name, definition: env.connection.view_definition(view_name))
13
- env.dump.tables[view.name] = view
14
- env.dump.depends(view.name, view.definition.scan(re_view_referent).flatten)
15
- end
16
- end
17
-
18
- # quacks like a SchemaMonkey Dump::Table
19
- class View < KeyStruct[:name, :definition]
20
- def assemble(stream)
21
- stream.puts(" create_view #{name.inspect}, #{definition.inspect}, :force => true\n")
22
- end
23
- end
24
- end
25
- end
26
-
27
- module Query
28
- module Tables
29
-
30
- module Mysql
31
- def after(env)
32
- Tables.filter_out_views(env)
33
- end
34
- end
35
-
36
- module Sqlite3
37
- def after(env)
38
- Tables.filter_out_views(env)
39
- end
40
- end
41
-
42
- def self.filter_out_views(env)
43
- env.tables -= env.connection.views(env.query_name)
44
- end
45
- end
46
- end
47
- end
48
-
49
- end
@@ -1,97 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "with multiple schemas" do
4
- def connection
5
- ActiveRecord::Base.connection
6
- end
7
-
8
- before(:all) do
9
- newdb = case connection.adapter_name
10
- when /^mysql/i then "CREATE SCHEMA IF NOT EXISTS schema_plus_views_test2"
11
- when /^postgresql/i then "CREATE SCHEMA schema_plus_views_test2"
12
- when /^sqlite/i then "ATTACH ':memory:' AS schema_plus_views_test2"
13
- end
14
- begin
15
- ActiveRecord::Base.connection.execute newdb
16
- rescue ActiveRecord::StatementInvalid => e
17
- raise unless e.message =~ /already exists/
18
- end
19
-
20
- class User < ::ActiveRecord::Base ; end
21
- end
22
-
23
- before(:each) do
24
- define_schema(:auto_create => false) do
25
- create_table :users, :force => true do |t|
26
- t.string :login
27
- end
28
- end
29
-
30
- connection.execute 'DROP TABLE IF EXISTS schema_plus_views_test2.users'
31
- connection.execute 'CREATE TABLE schema_plus_views_test2.users (id ' + case connection.adapter_name
32
- when /^mysql/i then "integer primary key auto_increment"
33
- when /^postgresql/i then "serial primary key"
34
- when /^sqlite/i then "integer primary key autoincrement"
35
- end + ", login varchar(255))"
36
- end
37
-
38
- context "with views in each schema" do
39
- around(:each) do |example|
40
- begin
41
- example.run
42
- ensure
43
- connection.execute 'DROP VIEW schema_plus_views_test2.myview' rescue nil
44
- connection.execute 'DROP VIEW myview' rescue nil
45
- end
46
- end
47
-
48
- before(:each) do
49
- connection.views.each { |view| connection.drop_view view }
50
- connection.execute 'CREATE VIEW schema_plus_views_test2.myview AS SELECT * FROM users'
51
- end
52
-
53
- it "should not find views in other schema" do
54
- expect(connection.views).to be_empty
55
- end
56
-
57
- it "should find views in this schema" do
58
- connection.execute 'CREATE VIEW myview AS SELECT * FROM users'
59
- expect(connection.views).to eq(['myview'])
60
- end
61
- end
62
-
63
- context "when using PostGIS", :postgresql => :only do
64
- before(:all) do
65
- begin
66
- connection.execute "CREATE SCHEMA postgis"
67
- rescue ActiveRecord::StatementInvalid => e
68
- raise unless e.message =~ /already exists/
69
- end
70
- end
71
-
72
- around(:each) do |example|
73
- begin
74
- connection.execute "SET search_path to '$user','public','postgis'"
75
- example.run
76
- ensure
77
- connection.execute "SET search_path to '$user','public'"
78
- end
79
- end
80
-
81
- before(:each) do
82
- allow(connection).to receive(:adapter_name).and_return('PostGIS')
83
- end
84
-
85
- it "should hide views in postgis schema" do
86
- begin
87
- connection.create_view "postgis.hidden", "select 1", :force => true
88
- connection.create_view :myview, "select 2", :force => true
89
- expect(connection.views).to eq(["myview"])
90
- ensure
91
- connection.execute 'DROP VIEW postgis.hidden' rescue nil
92
- connection.execute 'DROP VIEW myview' rescue nil
93
- end
94
- end
95
- end
96
-
97
- end
@@ -1,194 +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 ActiveRecord do
13
-
14
- let(:schema) { ActiveRecord::Schema }
15
-
16
- let(:migration) { ActiveRecord::Migration }
17
-
18
- let(:connection) { ActiveRecord::Base.connection }
19
-
20
- context "views" do
21
-
22
- around(:each) do |example|
23
- define_schema_and_data
24
- example.run
25
- drop_definitions
26
- end
27
-
28
- it "should query correctly" do
29
- expect(AOnes.all.collect(&:s)).to eq(%W[one_one one_two])
30
- expect(ABOnes.all.collect(&:s)).to eq(%W[one_one])
31
- end
32
-
33
- it "should instrospect" do
34
- # for postgresql, ignore views named pg_*
35
- expect(connection.views.sort).to eq(%W[a_ones ab_ones])
36
- expect(connection.view_definition('a_ones')).to match(%r{^ ?SELECT .*b.*,.*s.* FROM .*items.* WHERE .*a.* = 1}mi)
37
- expect(connection.view_definition('ab_ones')).to match(%r{^ ?SELECT .*s.* FROM .*a_ones.* WHERE .*b.* = 1}mi)
38
- end
39
-
40
- it "should not be listed as a table" do
41
- expect(connection.tables).not_to include('a_ones')
42
- expect(connection.tables).not_to include('ab_ones')
43
- end
44
-
45
-
46
- it "should be included in schema dump" do
47
- expect(dump).to match(%r{create_view "a_ones", " ?SELECT .*b.*,.*s.* FROM .*items.* WHERE .*a.* = 1.*, :force => true}mi)
48
- expect(dump).to match(%r{create_view "ab_ones", " ?SELECT .*s.* FROM .*a_ones.* WHERE .*b.* = 1.*, :force => true}mi)
49
- end
50
-
51
- it "should be included in schema dump in dependency order" do
52
- expect(dump).to match(%r{create_table "items".*create_view "a_ones".*create_view "ab_ones"}m)
53
- end
54
-
55
- it "should not be included in schema if listed in ignore_tables" do
56
- dump(ignore_tables: /b_/) do |dump|
57
- expect(dump).to match(%r{create_view "a_ones", " ?SELECT .*b.*,.*s.* FROM .*items.* WHERE .*a.* = 1.*, :force => true}mi)
58
- expect(dump).not_to match(%r{"ab_ones"})
59
- end
60
- end
61
-
62
-
63
- it "dump should not reference current database" do
64
- # why check this? mysql default to providing the view definition
65
- # with tables explicitly scoped to the current database, which
66
- # resulted in the dump being bound to the current database. this
67
- # caused trouble for rails, in which creates the schema dump file
68
- # when in the (say) development database, but then uses it to
69
- # initialize the test database when testing. this meant that the
70
- # test database had views into the development database.
71
- db = connection.respond_to?(:current_database)? connection.current_database : SchemaDev::Rspec.db_configuration[:database]
72
- expect(dump).not_to match(%r{#{connection.quote_table_name(db)}[.]})
73
- end
74
-
75
- context "duplicate view creation" do
76
- around(:each) do |example|
77
- migration.suppress_messages do
78
- begin
79
- migration.create_view('dupe_me', 'SELECT * FROM items WHERE (a=1)')
80
- example.run
81
- ensure
82
- migration.drop_view('dupe_me')
83
- end
84
- end
85
- end
86
-
87
-
88
- it "should raise an error by default" do
89
- expect {migration.create_view('dupe_me', 'SELECT * FROM items WHERE (a=2)')}.to raise_error ActiveRecord::StatementInvalid
90
- end
91
-
92
- it "should override existing definition if :force true" do
93
- migration.create_view('dupe_me', 'SELECT * FROM items WHERE (a=2)', :force => true)
94
- expect(connection.view_definition('dupe_me')).to match(%r{WHERE .*a.*=.*2}i)
95
- end
96
- end
97
-
98
- context "dropping views" do
99
- it "should raise an error if the view doesn't exist" do
100
- expect { migration.drop_view('doesnt_exist') }.to raise_error ActiveRecord::StatementInvalid
101
- end
102
-
103
- it "should fail silently when using if_exists option" do
104
- expect { migration.drop_view('doesnt_exist', :if_exists => true) }.not_to raise_error
105
- end
106
-
107
- context "with a view that exists" do
108
- before { migration.create_view('view_that_exists', 'SELECT * FROM items WHERE (a=1)') }
109
-
110
- it "should succeed" do
111
- migration.drop_view('view_that_exists')
112
- expect(connection.views).not_to include('view_that_exists')
113
- end
114
- end
115
- end
116
-
117
- context "in mysql", :mysql => :only do
118
-
119
- around(:each) do |example|
120
- migration.suppress_messages do
121
- begin
122
- migration.drop_view :check if connection.views.include? 'check'
123
- example.run
124
- ensure
125
- migration.drop_view :check if connection.views.include? 'check'
126
- end
127
- end
128
- end
129
-
130
- it "should introspect WITH CHECK OPTION" do
131
- migration.create_view :check, 'SELECT * FROM items WHERE (a=2) WITH CHECK OPTION'
132
- expect(connection.view_definition('check')).to match(%r{WITH CASCADED CHECK OPTION$})
133
- end
134
-
135
- it "should introspect WITH CASCADED CHECK OPTION" do
136
- migration.create_view :check, 'SELECT * FROM items WHERE (a=2) WITH CASCADED CHECK OPTION'
137
- expect(connection.view_definition('check')).to match(%r{WITH CASCADED CHECK OPTION$})
138
- end
139
-
140
- it "should introspect WITH LOCAL CHECK OPTION" do
141
- migration.create_view :check, 'SELECT * FROM items WHERE (a=2) WITH LOCAL CHECK OPTION'
142
- expect(connection.view_definition('check')).to match(%r{WITH LOCAL CHECK OPTION$})
143
- end
144
- end
145
- end
146
-
147
- protected
148
-
149
- def define_schema_and_data
150
- migration.suppress_messages do
151
- connection.views.each do |view| connection.drop_view view end
152
- connection.tables.each do |table| connection.drop_table table, cascade: true end
153
-
154
- schema.define do
155
-
156
- create_table :items, :force => true do |t|
157
- t.integer :a
158
- t.integer :b
159
- t.string :s
160
- end
161
-
162
- create_view :a_ones, Item.select('b, s').where(:a => 1)
163
- create_view :ab_ones, "select s from a_ones where b = 1"
164
- create_view :pg_dummy_internal, "select 1" if SchemaDev::Rspec::Helpers.postgresql?
165
- end
166
- end
167
- connection.execute "insert into items (a, b, s) values (1, 1, 'one_one')"
168
- connection.execute "insert into items (a, b, s) values (1, 2, 'one_two')"
169
- connection.execute "insert into items (a, b, s) values (2, 1, 'two_one')"
170
- connection.execute "insert into items (a, b, s) values (2, 2, 'two_two')"
171
-
172
- end
173
-
174
- def drop_definitions
175
- migration.suppress_messages do
176
- schema.define do
177
- drop_view "ab_ones"
178
- drop_view "a_ones"
179
- drop_table "items"
180
- drop_view :pg_dummy_internal if SchemaDev::Rspec::Helpers.postgresql?
181
- end
182
- end
183
- end
184
-
185
- def dump(opts={})
186
- StringIO.open { |stream|
187
- ActiveRecord::SchemaDumper.ignore_tables = Array.wrap(opts[:ignore_tables])
188
- ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
189
- yield stream.string if block_given?
190
- stream.string
191
- }
192
- end
193
-
194
- end