db_leftovers 0.4.0 → 0.5.0
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.
- data/README.html +36 -13
- data/README.md +32 -10
- data/Rakefile +4 -0
- data/VERSION +1 -1
- data/db_leftovers.gemspec +1 -1
- data/lib/db_leftovers/database_interface.rb +57 -2
- data/lib/db_leftovers/dsl.rb +22 -7
- data/lib/db_leftovers/foreign_key.rb +5 -5
- data/lib/db_leftovers/index.rb +9 -1
- data/spec/db_leftovers_spec.rb +54 -44
- metadata +2 -2
data/README.html
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
<h1>db_leftovers</h1>
|
2
2
|
|
3
|
-
<p>db_leftovers lets you define indexes
|
3
|
+
<p>db_leftovers lets you define indexes, foreign keys, and CHECK constraints for your Rails app
|
4
4
|
in one place using an easy-to-read DSL,
|
5
5
|
then run a rake task to bring your database up-to-date.
|
6
|
-
I wrote this because I didn't want indexes and
|
7
|
-
This was particularly a problem for Heroku projects, because <code>db:push</code> and <code>db:pull</code> do not transfer your foreign keys.
|
6
|
+
I wrote this because I didn't want indexes and constraints scattered throughout my migrations or buried in my <code>schema.rb</code>, and I wanted a command I could run to ensure that they matched across my development, test, staging, and production databases.
|
7
|
+
This was particularly a problem for Heroku projects, because <code>db:push</code> and <code>db:pull</code> do not transfer your foreign keys or other constraints.
|
8
8
|
But now that it's written, I'm finding it useful on non-Heroku projects as well.</p>
|
9
9
|
|
10
10
|
<p>At present db_leftovers works only on PostgreSQL databases,
|
@@ -12,9 +12,9 @@ but it could easily be extended to cover other RDBMSes.</p>
|
|
12
12
|
|
13
13
|
<h2>Configuration File</h2>
|
14
14
|
|
15
|
-
<p>db_leftovers reads a file named <code>config/db_leftovers.rb</code> to find out which indexes and
|
15
|
+
<p>db_leftovers reads a file named <code>config/db_leftovers.rb</code> to find out which indexes and constraints you want in your database. This file is a DSL implemented in Ruby, sort of like <code>config/routes.rb</code>. There are only a few methods:</p>
|
16
16
|
|
17
|
-
<h3>index
|
17
|
+
<h3>index(table_name, columns, [opts])</h3>
|
18
18
|
|
19
19
|
<p>This ensures that you have an index on the given table and column(s). The <code>columns</code> parameter can be either a string or a list of strings. Opts is a hash with the following possible keys:</p>
|
20
20
|
|
@@ -31,10 +31,10 @@ index :books, [:publisher_id, :published_at]
|
|
31
31
|
index :books, :isbn, :unique => true
|
32
32
|
</code></pre>
|
33
33
|
|
34
|
-
<h3>foreign_key
|
34
|
+
<h3>foreign_key(from_table, from_column, to_table, [to_column, [opts]])</h3>
|
35
35
|
|
36
36
|
<p>This ensures that you have a foreign key relating the given tables and columns.
|
37
|
-
All parameters are strings except <code>opts</code>, which is a hash.
|
37
|
+
All parameters are strings/symbols except <code>opts</code>, which is a hash.
|
38
38
|
If you don't pass anything for <code>opts</code>, you can leave off the <code>to_column</code> parameter, and it will default to <code>:id</code>.
|
39
39
|
These options are supported:</p>
|
40
40
|
|
@@ -52,17 +52,28 @@ foreign_key :books, :publisher_id, :publishers
|
|
52
52
|
foreign_key :pages, :book_id, :books, :id, :cascade => true
|
53
53
|
</code></pre>
|
54
54
|
|
55
|
-
<h3>
|
55
|
+
<h3>check(constraint_name, on_table, expression)</h3>
|
56
|
+
|
57
|
+
<p>This ensures that you have a CHECK constraint on the given table with the given name and expression.
|
58
|
+
All parameters are strings or symbols.</p>
|
59
|
+
|
60
|
+
<h4>Examples</h4>
|
61
|
+
|
62
|
+
<pre><code>check :books, :books_have_positive_pages, 'page_count > 0'
|
63
|
+
</code></pre>
|
64
|
+
|
65
|
+
<h3>table(table_name, &block)</h3>
|
56
66
|
|
57
67
|
<p>The <code>table</code> call is just a convenience so you can group all a table's indexes and foreign keys together and not keep repeating the table name. You use it like this:</p>
|
58
68
|
|
59
69
|
<pre><code>table :books do
|
60
70
|
index :author_id
|
61
71
|
foreign_key :publisher_id, :publishers
|
72
|
+
check :books_have_positive_pages, 'page_count > 0'
|
62
73
|
end
|
63
74
|
</code></pre>
|
64
75
|
|
65
|
-
<p>You can repeat <code>table</code> calls for the same table several times if you like. This lets you put your indexes in one place and your foreign keys in another.</p>
|
76
|
+
<p>You can repeat <code>table</code> calls for the same table several times if you like. This lets you put your indexes in one place and your foreign keys in another, for example.</p>
|
66
77
|
|
67
78
|
<h2>Running db_leftovers</h2>
|
68
79
|
|
@@ -76,8 +87,20 @@ end
|
|
76
87
|
<ul>
|
77
88
|
<li><p>db_leftovers only supports PostgreSQL databases.
|
78
89
|
If you want to add support for something else, just send me a pull request!</p></li>
|
79
|
-
<li><p>db_leftovers will not notice if an
|
80
|
-
Right now it only checks for existence/non-existence
|
90
|
+
<li><p>db_leftovers will not notice if an foreign key/constraint definition changes.
|
91
|
+
Right now it only checks for existence/non-existence.
|
92
|
+
You can get around this by adding a version number to your constraint names,
|
93
|
+
so if you want to force books to have at least 12 pages, you can say this:</p>
|
94
|
+
|
95
|
+
<p><code>check :books_have_positive_pages2, 'page_count >= 12'</code></p>
|
96
|
+
|
97
|
+
<p>Then the old constraint will be dropped and the new one will be added.</p>
|
98
|
+
|
99
|
+
<p>However, db_leftovers <em>does</em> check for index definitions, so if you
|
100
|
+
make an existing index unique, add a column, remove a WHERE clause, or
|
101
|
+
anything else, it will notice and drop and re-create the index.
|
102
|
+
I'm working on doing the same thing for foreign keys/constraints,
|
103
|
+
but it's not done just yet.</p></li>
|
81
104
|
<li><p>If your database is mostly up-to-date, then running the Rake task will spam
|
82
105
|
you with messages about how this index and that foreign key already exist.
|
83
106
|
These should be hidden by default and shown only if you request a higher
|
@@ -98,5 +121,5 @@ verbosity.</p></li>
|
|
98
121
|
|
99
122
|
<h2>Copyright</h2>
|
100
123
|
|
101
|
-
<p>Copyright (c) 2012 Paul A. Jungwirth.
|
102
|
-
further details.</p>
|
124
|
+
<p>Copyright (c) 2012 Paul A. Jungwirth.
|
125
|
+
See LICENSE.txt for further details.</p>
|
data/README.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
db\_leftovers
|
2
2
|
=============
|
3
3
|
|
4
|
-
db\_leftovers lets you define indexes
|
4
|
+
db\_leftovers lets you define indexes, foreign keys, and CHECK constraints for your Rails app
|
5
5
|
in one place using an easy-to-read DSL,
|
6
6
|
then run a rake task to bring your database up-to-date.
|
7
|
-
I wrote this because I didn't want indexes and
|
8
|
-
This was particularly a problem for Heroku projects, because `db:push` and `db:pull` do not transfer your foreign keys.
|
7
|
+
I wrote this because I didn't want indexes and constraints scattered throughout my migrations or buried in my `schema.rb`, and I wanted a command I could run to ensure that they matched across my development, test, staging, and production databases.
|
8
|
+
This was particularly a problem for Heroku projects, because `db:push` and `db:pull` do not transfer your foreign keys or other constraints.
|
9
9
|
But now that it's written, I'm finding it useful on non-Heroku projects as well.
|
10
10
|
|
11
11
|
At present db\_leftovers works only on PostgreSQL databases,
|
@@ -14,9 +14,9 @@ but it could easily be extended to cover other RDBMSes.
|
|
14
14
|
Configuration File
|
15
15
|
------------------
|
16
16
|
|
17
|
-
db\_leftovers reads a file named `config/db_leftovers.rb` to find out which indexes and
|
17
|
+
db\_leftovers reads a file named `config/db_leftovers.rb` to find out which indexes and constraints you want in your database. This file is a DSL implemented in Ruby, sort of like `config/routes.rb`. There are only a few methods:
|
18
18
|
|
19
|
-
### index
|
19
|
+
### index(table\_name, columns, [opts])
|
20
20
|
|
21
21
|
This ensures that you have an index on the given table and column(s). The `columns` parameter can be either a string or a list of strings. Opts is a hash with the following possible keys:
|
22
22
|
|
@@ -32,10 +32,10 @@ This ensures that you have an index on the given table and column(s). The `colum
|
|
32
32
|
index :books, [:publisher_id, :published_at]
|
33
33
|
index :books, :isbn, :unique => true
|
34
34
|
|
35
|
-
### foreign\_key
|
35
|
+
### foreign\_key(from\_table, from\_column, to\_table, [to\_column, [opts]])
|
36
36
|
|
37
37
|
This ensures that you have a foreign key relating the given tables and columns.
|
38
|
-
All parameters are strings except `opts`, which is a hash.
|
38
|
+
All parameters are strings/symbols except `opts`, which is a hash.
|
39
39
|
If you don't pass anything for `opts`, you can leave off the `to_column` parameter, and it will default to `:id`.
|
40
40
|
These options are supported:
|
41
41
|
|
@@ -50,16 +50,26 @@ These options are mutually exclusive. They should probably be consolidated into
|
|
50
50
|
foreign_key :books, :publisher_id, :publishers
|
51
51
|
foreign_key :pages, :book_id, :books, :id, :cascade => true
|
52
52
|
|
53
|
-
###
|
53
|
+
### check(constraint\_name, on\_table, expression)
|
54
|
+
|
55
|
+
This ensures that you have a CHECK constraint on the given table with the given name and expression.
|
56
|
+
All parameters are strings or symbols.
|
57
|
+
|
58
|
+
#### Examples
|
59
|
+
|
60
|
+
check :books, :books_have_positive_pages, 'page_count > 0'
|
61
|
+
|
62
|
+
### table(table\_name, &block)
|
54
63
|
|
55
64
|
The `table` call is just a convenience so you can group all a table's indexes and foreign keys together and not keep repeating the table name. You use it like this:
|
56
65
|
|
57
66
|
table :books do
|
58
67
|
index :author_id
|
59
68
|
foreign_key :publisher_id, :publishers
|
69
|
+
check :books_have_positive_pages, 'page_count > 0'
|
60
70
|
end
|
61
71
|
|
62
|
-
You can repeat `table` calls for the same table several times if you like. This lets you put your indexes in one place and your foreign keys in another.
|
72
|
+
You can repeat `table` calls for the same table several times if you like. This lets you put your indexes in one place and your foreign keys in another, for example.
|
63
73
|
|
64
74
|
|
65
75
|
Running db\_leftovers
|
@@ -76,8 +86,20 @@ Known Issues
|
|
76
86
|
* db\_leftovers only supports PostgreSQL databases.
|
77
87
|
If you want to add support for something else, just send me a pull request!
|
78
88
|
|
79
|
-
* db\_leftovers will not notice if an
|
89
|
+
* db\_leftovers will not notice if an foreign key/constraint definition changes.
|
80
90
|
Right now it only checks for existence/non-existence.
|
91
|
+
You can get around this by adding a version number to your constraint names,
|
92
|
+
so if you want to force books to have at least 12 pages, you can say this:
|
93
|
+
|
94
|
+
`check :books_have_positive_pages2, 'page_count >= 12'`
|
95
|
+
|
96
|
+
Then the old constraint will be dropped and the new one will be added.
|
97
|
+
|
98
|
+
However, db\_leftovers *does* check for index definitions, so if you
|
99
|
+
make an existing index unique, add a column, remove a WHERE clause, or
|
100
|
+
anything else, it will notice and drop and re-create the index.
|
101
|
+
I'm working on doing the same thing for foreign keys/constraints,
|
102
|
+
but it's not done just yet.
|
81
103
|
|
82
104
|
* If your database is mostly up-to-date, then running the Rake task will spam
|
83
105
|
you with messages about how this index and that foreign key already exist.
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/db_leftovers.gemspec
CHANGED
@@ -4,6 +4,7 @@ module DBLeftovers
|
|
4
4
|
|
5
5
|
def lookup_all_indexes
|
6
6
|
ret = {}
|
7
|
+
=begin
|
7
8
|
sql = <<-EOQ
|
8
9
|
SELECT n.nspname as "Schema", c.relname as "Name",
|
9
10
|
CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' END as "Type",
|
@@ -22,11 +23,64 @@ module DBLeftovers
|
|
22
23
|
ORDER BY 1,2;
|
23
24
|
EOQ
|
24
25
|
ActiveRecord::Base.connection.select_rows(sql).each do |schema, index_name, object_type, owner, table_name|
|
25
|
-
|
26
|
+
=end
|
27
|
+
sql = <<-EOQ
|
28
|
+
SELECT ix.indexrelid,
|
29
|
+
ix.indrelid,
|
30
|
+
t.relname AS table_name,
|
31
|
+
i.relname AS index_name,
|
32
|
+
ix.indisunique AS is_unique,
|
33
|
+
array_to_string(ix.indkey, ',') AS column_numbers,
|
34
|
+
pg_get_expr(ix.indpred, ix.indrelid) AS where_clause
|
35
|
+
FROM pg_class t,
|
36
|
+
pg_class i,
|
37
|
+
pg_index ix,
|
38
|
+
pg_namespace n
|
39
|
+
WHERE t.oid = ix.indrelid
|
40
|
+
AND n.oid = t.relnamespace
|
41
|
+
AND i.oid = ix.indexrelid
|
42
|
+
AND t.relkind = 'r'
|
43
|
+
AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
|
44
|
+
AND pg_catalog.pg_table_is_visible(t.oid)
|
45
|
+
AND t.relname NOT IN ('delayed_jobs', 'schema_migrations')
|
46
|
+
AND NOT ix.indisprimary
|
47
|
+
GROUP BY t.relname,
|
48
|
+
i.relname,
|
49
|
+
ix.indisunique,
|
50
|
+
ix.indexrelid,
|
51
|
+
ix.indrelid
|
52
|
+
ix.indkey,
|
53
|
+
ix.indpred,
|
54
|
+
ORDER BY t.relname, i.relname
|
55
|
+
EOQ
|
56
|
+
ActiveRecord::Base.connection.select_rows(sql).each do |indexrelid, indrelid, table_name, index_name, is_unique, column_numbers, where_clause|
|
57
|
+
ret[index_name] = Index.new(
|
58
|
+
table_name,
|
59
|
+
column_names_for_index(indrelid, column_numbers.split(",")),
|
60
|
+
unique: is_unique,
|
61
|
+
where: where_clause,
|
62
|
+
name: index_name
|
63
|
+
)
|
26
64
|
end
|
27
65
|
return ret
|
28
66
|
end
|
29
67
|
|
68
|
+
|
69
|
+
|
70
|
+
def column_names_for_index(table_id, column_numbers)
|
71
|
+
column_numbers.map do |c|
|
72
|
+
sql = <<-EOQ
|
73
|
+
SELECT attname
|
74
|
+
FROM pg_attribute
|
75
|
+
WHERE attrelid = #{table_id}
|
76
|
+
AND attnum = #{c}
|
77
|
+
EOQ
|
78
|
+
ActiveRecord::Base.connection.select_value(sql)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
|
30
84
|
def lookup_all_foreign_keys
|
31
85
|
ret = {}
|
32
86
|
sql = <<-EOQ
|
@@ -109,6 +163,7 @@ module DBLeftovers
|
|
109
163
|
ActiveRecord::Base.connection.execute(sql)
|
110
164
|
end
|
111
165
|
|
112
|
-
|
166
|
+
private
|
113
167
|
|
168
|
+
end
|
114
169
|
end
|
data/lib/db_leftovers/dsl.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
module DBLeftovers
|
2
2
|
|
3
3
|
class DSL
|
4
|
+
|
5
|
+
STATUS_EXISTS = 'exists'
|
6
|
+
STATUS_CHANGED = 'changed'
|
7
|
+
STATUS_NEW = 'new'
|
8
|
+
|
4
9
|
def initialize
|
5
10
|
@db = DatabaseInterface.new
|
6
11
|
@indexes_by_table = {} # Set from the DSL
|
@@ -44,9 +49,14 @@ module DBLeftovers
|
|
44
49
|
@indexes_by_table.each do |table_name, indexes|
|
45
50
|
indexes.each do |idx|
|
46
51
|
# puts "#{idx.table_name}.[#{idx.column_names.join(',')}]"
|
47
|
-
|
52
|
+
case index_status(idx)
|
53
|
+
when STATUS_EXISTS
|
48
54
|
puts "Index already exists: #{idx.index_name} on #{idx.table_name}"
|
49
|
-
|
55
|
+
when STATUS_CHANGED
|
56
|
+
@db.execute_drop_index(idx.table_name, idx.index_name)
|
57
|
+
@db.execute_add_index(idx)
|
58
|
+
puts "Dropped & re-created index: #{idx.index_name} on #{idx.table_name}"
|
59
|
+
when STATUS_NEW
|
50
60
|
@db.execute_add_index(idx)
|
51
61
|
puts "Created index: #{idx.index_name} on #{idx.table_name}"
|
52
62
|
end
|
@@ -55,11 +65,11 @@ module DBLeftovers
|
|
55
65
|
end
|
56
66
|
|
57
67
|
# Now drop any old indexes that are no longer in the definition file:
|
58
|
-
@old_indexes.each do |index_name,
|
68
|
+
@old_indexes.each do |index_name, idx|
|
59
69
|
if not @new_indexes[index_name]
|
60
70
|
# puts "#{index_name} #{table_name}"
|
61
|
-
@db.execute_drop_index(table_name, index_name)
|
62
|
-
puts "Dropped index: #{index_name} on #{table_name}"
|
71
|
+
@db.execute_drop_index(idx.table_name, index_name)
|
72
|
+
puts "Dropped index: #{index_name} on #{idx.table_name}"
|
63
73
|
end
|
64
74
|
end
|
65
75
|
end
|
@@ -131,8 +141,13 @@ module DBLeftovers
|
|
131
141
|
index_name[0,63]
|
132
142
|
end
|
133
143
|
|
134
|
-
def
|
135
|
-
@old_indexes[truncate_index_name(idx.index_name)]
|
144
|
+
def index_status(idx)
|
145
|
+
old = @old_indexes[truncate_index_name(idx.index_name)]
|
146
|
+
if old
|
147
|
+
return old.equals(idx) ? STATUS_EXISTS : STATUS_CHANGED
|
148
|
+
else
|
149
|
+
return STATUS_NEW
|
150
|
+
end
|
136
151
|
end
|
137
152
|
|
138
153
|
def foreign_key_exists?(fk)
|
@@ -11,11 +11,11 @@ module DBLeftovers
|
|
11
11
|
opts.keys.each do |k|
|
12
12
|
raise "Unknown option: #{k}" unless [:set_null, :cascade].include?(k)
|
13
13
|
end
|
14
|
-
@constraint_name = constraint_name
|
15
|
-
@from_table = from_table
|
16
|
-
@from_column = from_column
|
17
|
-
@to_table = to_table
|
18
|
-
@to_column = to_column
|
14
|
+
@constraint_name = constraint_name.to_s
|
15
|
+
@from_table = from_table.to_s
|
16
|
+
@from_column = from_column.to_s
|
17
|
+
@to_table = to_table.to_s
|
18
|
+
@to_column = to_column.to_s
|
19
19
|
|
20
20
|
@set_null = opts[:set_null]
|
21
21
|
@cascade = opts[:cascade]
|
data/lib/db_leftovers/index.rb
CHANGED
@@ -21,7 +21,15 @@ module DBLeftovers
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def unique?
|
24
|
-
|
24
|
+
!!@unique
|
25
|
+
end
|
26
|
+
|
27
|
+
def equals(other)
|
28
|
+
other.table_name == table_name and
|
29
|
+
other.column_names == column_names and
|
30
|
+
other.index_name == index_name and
|
31
|
+
other.where_clause == where_clause and
|
32
|
+
other.unique == unique
|
25
33
|
end
|
26
34
|
|
27
35
|
private
|
data/spec/db_leftovers_spec.rb
CHANGED
@@ -24,11 +24,11 @@ class DBLeftovers::DatabaseInterface
|
|
24
24
|
)
|
25
25
|
end
|
26
26
|
|
27
|
-
def self.starts_with(indexes, foreign_keys, constraints=
|
27
|
+
def self.starts_with(indexes=[], foreign_keys=[], constraints=[])
|
28
28
|
# Convert symbols to strings:
|
29
|
-
@@indexes = indexes.
|
30
|
-
@@foreign_keys = foreign_keys.
|
31
|
-
@@constraints = constraints.
|
29
|
+
@@indexes = Hash[indexes.map{|idx| [idx.index_name, idx]}]
|
30
|
+
@@foreign_keys = Hash[foreign_keys.map{|fk| [fk.constraint_name, fk]}]
|
31
|
+
@@constraints = Hash[constraints.map{|chk| [chk.constraint_name, chk]}]
|
32
32
|
end
|
33
33
|
|
34
34
|
def lookup_all_indexes
|
@@ -58,14 +58,14 @@ end
|
|
58
58
|
describe DBLeftovers do
|
59
59
|
|
60
60
|
it "should allow an empty definition" do
|
61
|
-
DBLeftovers::DatabaseInterface.starts_with
|
61
|
+
DBLeftovers::DatabaseInterface.starts_with
|
62
62
|
DBLeftovers::Definition.define do
|
63
63
|
end
|
64
64
|
DBLeftovers::DatabaseInterface.sqls.should be_empty
|
65
65
|
end
|
66
66
|
|
67
67
|
it "should allow an empty table definition" do
|
68
|
-
DBLeftovers::DatabaseInterface.starts_with
|
68
|
+
DBLeftovers::DatabaseInterface.starts_with
|
69
69
|
DBLeftovers::Definition.define do
|
70
70
|
table :books do
|
71
71
|
end
|
@@ -74,7 +74,7 @@ describe DBLeftovers do
|
|
74
74
|
end
|
75
75
|
|
76
76
|
it "should create indexes on an empty database" do
|
77
|
-
DBLeftovers::DatabaseInterface.starts_with
|
77
|
+
DBLeftovers::DatabaseInterface.starts_with
|
78
78
|
DBLeftovers::Definition.define do
|
79
79
|
index :books, :shelf_id
|
80
80
|
index :books, :publisher_id, :where => 'published'
|
@@ -96,7 +96,7 @@ describe DBLeftovers do
|
|
96
96
|
|
97
97
|
|
98
98
|
it "should create table-prefixed indexes on an empty database" do
|
99
|
-
DBLeftovers::DatabaseInterface.starts_with
|
99
|
+
DBLeftovers::DatabaseInterface.starts_with
|
100
100
|
DBLeftovers::Definition.define do
|
101
101
|
table :books do
|
102
102
|
index :shelf_id
|
@@ -120,7 +120,7 @@ describe DBLeftovers do
|
|
120
120
|
|
121
121
|
|
122
122
|
it "should create foreign keys on an empty database" do
|
123
|
-
DBLeftovers::DatabaseInterface.starts_with
|
123
|
+
DBLeftovers::DatabaseInterface.starts_with
|
124
124
|
DBLeftovers::Definition.define do
|
125
125
|
foreign_key :books, :shelf_id, :shelves
|
126
126
|
foreign_key :books, :publisher_id, :publishers, :id, :set_null => true
|
@@ -152,7 +152,7 @@ describe DBLeftovers do
|
|
152
152
|
|
153
153
|
|
154
154
|
it "should create table-prefixed foreign keys on an empty database" do
|
155
|
-
DBLeftovers::DatabaseInterface.starts_with
|
155
|
+
DBLeftovers::DatabaseInterface.starts_with
|
156
156
|
DBLeftovers::Definition.define do
|
157
157
|
table :books do
|
158
158
|
foreign_key :shelf_id, :shelves
|
@@ -186,11 +186,10 @@ describe DBLeftovers do
|
|
186
186
|
|
187
187
|
|
188
188
|
it "should not create indexes when they already exist" do
|
189
|
-
DBLeftovers::DatabaseInterface.starts_with(
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
}, {})
|
189
|
+
DBLeftovers::DatabaseInterface.starts_with([
|
190
|
+
DBLeftovers::Index.new(:books, :shelf_id),
|
191
|
+
DBLeftovers::Index.new(:books, :publisher_id, :where => 'published')
|
192
|
+
])
|
194
193
|
DBLeftovers::Definition.define do
|
195
194
|
index :books, :shelf_id
|
196
195
|
index :books, :publisher_id, :where => 'published'
|
@@ -200,13 +199,29 @@ describe DBLeftovers do
|
|
200
199
|
|
201
200
|
|
202
201
|
|
202
|
+
it "should create indexes when they have been redefined" do
|
203
|
+
DBLeftovers::DatabaseInterface.starts_with([
|
204
|
+
DBLeftovers::Index.new(:books, :shelf_id),
|
205
|
+
DBLeftovers::Index.new(:books, :publisher_id, :where => 'published'),
|
206
|
+
DBLeftovers::Index.new(:books, :isbn, :unique => true)
|
207
|
+
])
|
208
|
+
DBLeftovers::Definition.define do
|
209
|
+
index :books, :shelf_id, :where => 'isbn IS NOT NULL'
|
210
|
+
index :books, :publisher_id
|
211
|
+
index :books, :isbn
|
212
|
+
end
|
213
|
+
DBLeftovers::DatabaseInterface.sqls.should have(6).items
|
214
|
+
DBLeftovers::DatabaseInterface.sqls[0].should =~ /DROP INDEX index_books_on_shelf_id/
|
215
|
+
DBLeftovers::DatabaseInterface.sqls[1].should =~ /CREATE\s+INDEX index_books_on_shelf_id/
|
216
|
+
end
|
217
|
+
|
218
|
+
|
203
219
|
|
204
220
|
it "should not create table-prefixed indexes when they already exist" do
|
205
|
-
DBLeftovers::DatabaseInterface.starts_with(
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
}, {})
|
221
|
+
DBLeftovers::DatabaseInterface.starts_with([
|
222
|
+
DBLeftovers::Index.new(:books, :shelf_id),
|
223
|
+
DBLeftovers::Index.new(:books, :publisher_id, :where => 'published')
|
224
|
+
])
|
210
225
|
DBLeftovers::Definition.define do
|
211
226
|
table :books do
|
212
227
|
index :shelf_id
|
@@ -220,10 +235,9 @@ describe DBLeftovers do
|
|
220
235
|
|
221
236
|
|
222
237
|
it "should not create foreign keys when they already exist" do
|
223
|
-
DBLeftovers::DatabaseInterface.starts_with(
|
224
|
-
|
225
|
-
|
226
|
-
})
|
238
|
+
DBLeftovers::DatabaseInterface.starts_with([], [
|
239
|
+
DBLeftovers::ForeignKey.new('fk_books_shelf_id', 'books', 'shelf_id', 'shelves', 'id')
|
240
|
+
])
|
227
241
|
DBLeftovers::Definition.define do
|
228
242
|
foreign_key :books, :shelf_id, :shelves
|
229
243
|
end
|
@@ -233,10 +247,9 @@ describe DBLeftovers do
|
|
233
247
|
|
234
248
|
|
235
249
|
it "should not create table-prefixed foreign keys when they already exist" do
|
236
|
-
DBLeftovers::DatabaseInterface.starts_with(
|
237
|
-
|
238
|
-
|
239
|
-
})
|
250
|
+
DBLeftovers::DatabaseInterface.starts_with([], [
|
251
|
+
DBLeftovers::ForeignKey.new('fk_books_shelf_id', 'books', 'shelf_id', 'shelves', 'id')
|
252
|
+
])
|
240
253
|
DBLeftovers::Definition.define do
|
241
254
|
table :books do
|
242
255
|
foreign_key :shelf_id, :shelves
|
@@ -248,11 +261,10 @@ describe DBLeftovers do
|
|
248
261
|
|
249
262
|
|
250
263
|
it "should drop indexes when they are removed from the definition" do
|
251
|
-
DBLeftovers::DatabaseInterface.starts_with(
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
}, {})
|
264
|
+
DBLeftovers::DatabaseInterface.starts_with([
|
265
|
+
DBLeftovers::Index.new(:books, :shelf_id),
|
266
|
+
DBLeftovers::Index.new(:books, :publisher_id, :where => 'published')
|
267
|
+
])
|
256
268
|
DBLeftovers::Definition.define do
|
257
269
|
index :books, :shelf_id
|
258
270
|
end
|
@@ -265,12 +277,10 @@ describe DBLeftovers do
|
|
265
277
|
|
266
278
|
|
267
279
|
it "should drop foreign keys when they are removed from the definition" do
|
268
|
-
DBLeftovers::DatabaseInterface.starts_with(
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
'books', 'author_id', 'authors', 'id')
|
273
|
-
})
|
280
|
+
DBLeftovers::DatabaseInterface.starts_with([], [
|
281
|
+
DBLeftovers::ForeignKey.new('fk_books_shelf_id', 'books', 'shelf_id', 'shelves', 'id'),
|
282
|
+
DBLeftovers::ForeignKey.new('fk_books_author_id', 'books', 'author_id', 'authors', 'id')
|
283
|
+
])
|
274
284
|
DBLeftovers::Definition.define do
|
275
285
|
foreign_key :books, :shelf_id, :shelves
|
276
286
|
end
|
@@ -283,7 +293,7 @@ describe DBLeftovers do
|
|
283
293
|
|
284
294
|
|
285
295
|
it "should support creating multi-column indexes" do
|
286
|
-
DBLeftovers::DatabaseInterface.starts_with
|
296
|
+
DBLeftovers::DatabaseInterface.starts_with
|
287
297
|
DBLeftovers::Definition.define do
|
288
298
|
index :books, [:year, :title]
|
289
299
|
end
|
@@ -298,9 +308,9 @@ describe DBLeftovers do
|
|
298
308
|
|
299
309
|
|
300
310
|
it "should support dropping multi-column indexes" do
|
301
|
-
DBLeftovers::DatabaseInterface.starts_with(
|
302
|
-
|
303
|
-
|
311
|
+
DBLeftovers::DatabaseInterface.starts_with([
|
312
|
+
DBLeftovers::Index.new(:books, [:year, :title])
|
313
|
+
])
|
304
314
|
DBLeftovers::Definition.define do
|
305
315
|
end
|
306
316
|
DBLeftovers::DatabaseInterface.sqls.should have(1).item
|
@@ -312,7 +322,7 @@ describe DBLeftovers do
|
|
312
322
|
|
313
323
|
|
314
324
|
it "should allow mixing indexes and foreign keys in the same table" do
|
315
|
-
DBLeftovers::DatabaseInterface.starts_with
|
325
|
+
DBLeftovers::DatabaseInterface.starts_with
|
316
326
|
DBLeftovers::Definition.define do
|
317
327
|
table :books do
|
318
328
|
index :author_id
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: db_leftovers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -139,7 +139,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
139
139
|
version: '0'
|
140
140
|
segments:
|
141
141
|
- 0
|
142
|
-
hash:
|
142
|
+
hash: 4584251961758391352
|
143
143
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
144
|
none: false
|
145
145
|
requirements:
|