db_leftovers 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.html +3 -4
- data/README.md +3 -4
- data/VERSION +1 -1
- data/db_leftovers.gemspec +1 -1
- data/lib/db_leftovers/database_interface.rb +15 -35
- data/lib/db_leftovers/foreign_key.rb +17 -5
- data/spec/db_leftovers_spec.rb +57 -4
- metadata +2 -2
data/README.html
CHANGED
@@ -36,20 +36,19 @@ index :books, :isbn, :unique => true
|
|
36
36
|
<p>This ensures that you have a foreign key relating the given tables and columns.
|
37
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
|
+
The only option that is supported is <code>:on_delete</code>, which may have any of these values:</p>
|
40
40
|
|
41
41
|
<ul>
|
42
|
+
<li><code>nil</code> Indicates that attempting to delete the referenced row should fail (the default).</li>
|
42
43
|
<li><code>:set_null</code> Indicates that the foreign key should be set to null if the referenced row is deleted.</li>
|
43
44
|
<li><code>:cascade</code> Indicates that the referencing row should be deleted if the referenced row is deleted.</li>
|
44
45
|
</ul>
|
45
46
|
|
46
|
-
<p>These options are mutually exclusive. They should probably be consolidated into a single option like <code>:on_delete</code>.</p>
|
47
|
-
|
48
47
|
<h4>Examples</h4>
|
49
48
|
|
50
49
|
<pre><code>foreign_key :books, :author_id, :authors, :id
|
51
50
|
foreign_key :books, :publisher_id, :publishers
|
52
|
-
foreign_key :pages, :book_id, :books, :id, :
|
51
|
+
foreign_key :pages, :book_id, :books, :id, :on_delete => :cascade
|
53
52
|
</code></pre>
|
54
53
|
|
55
54
|
<h3>check(constraint_name, on_table, expression)</h3>
|
data/README.md
CHANGED
@@ -37,18 +37,17 @@ This ensures that you have an index on the given table and column(s). The `colum
|
|
37
37
|
This ensures that you have a foreign key relating the given tables and columns.
|
38
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
|
+
The only option that is supported is `:on_delete`, which may have any of these values:
|
41
41
|
|
42
|
+
* `nil` Indicates that attempting to delete the referenced row should fail (the default).
|
42
43
|
* `:set_null` Indicates that the foreign key should be set to null if the referenced row is deleted.
|
43
44
|
* `:cascade` Indicates that the referencing row should be deleted if the referenced row is deleted.
|
44
45
|
|
45
|
-
These options are mutually exclusive. They should probably be consolidated into a single option like `:on_delete`.
|
46
|
-
|
47
46
|
#### Examples
|
48
47
|
|
49
48
|
foreign_key :books, :author_id, :authors, :id
|
50
49
|
foreign_key :books, :publisher_id, :publishers
|
51
|
-
foreign_key :pages, :book_id, :books, :id, :
|
50
|
+
foreign_key :pages, :book_id, :books, :id, :on_delete => :cascade
|
52
51
|
|
53
52
|
### check(constraint\_name, on\_table, expression)
|
54
53
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.1
|
data/db_leftovers.gemspec
CHANGED
@@ -4,26 +4,6 @@ module DBLeftovers
|
|
4
4
|
|
5
5
|
def lookup_all_indexes
|
6
6
|
ret = {}
|
7
|
-
=begin
|
8
|
-
sql = <<-EOQ
|
9
|
-
SELECT n.nspname as "Schema", c.relname as "Name",
|
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",
|
11
|
-
u.usename as "Owner",
|
12
|
-
c2.relname as "Table"
|
13
|
-
FROM pg_catalog.pg_class c
|
14
|
-
JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid
|
15
|
-
JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid
|
16
|
-
LEFT JOIN pg_catalog.pg_user u ON u.usesysid = c.relowner
|
17
|
-
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
18
|
-
WHERE c.relkind IN ('i','')
|
19
|
-
AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
|
20
|
-
AND pg_catalog.pg_table_is_visible(c.oid)
|
21
|
-
AND c.relname NOT LIKE '%_pkey'
|
22
|
-
AND c2.relname NOT IN ('delayed_jobs', 'schema_migrations')
|
23
|
-
ORDER BY 1,2;
|
24
|
-
EOQ
|
25
|
-
ActiveRecord::Base.connection.select_rows(sql).each do |schema, index_name, object_type, owner, table_name|
|
26
|
-
=end
|
27
7
|
sql = <<-EOQ
|
28
8
|
SELECT ix.indexrelid,
|
29
9
|
ix.indrelid,
|
@@ -48,7 +28,7 @@ module DBLeftovers
|
|
48
28
|
i.relname,
|
49
29
|
ix.indisunique,
|
50
30
|
ix.indexrelid,
|
51
|
-
ix.indrelid
|
31
|
+
ix.indrelid,
|
52
32
|
ix.indkey,
|
53
33
|
ix.indpred,
|
54
34
|
ORDER BY t.relname, i.relname
|
@@ -67,20 +47,6 @@ module DBLeftovers
|
|
67
47
|
|
68
48
|
|
69
49
|
|
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
|
-
|
84
50
|
def lookup_all_foreign_keys
|
85
51
|
ret = {}
|
86
52
|
sql = <<-EOQ
|
@@ -165,5 +131,19 @@ module DBLeftovers
|
|
165
131
|
|
166
132
|
private
|
167
133
|
|
134
|
+
def column_names_for_index(table_id, column_numbers)
|
135
|
+
column_numbers.map do |c|
|
136
|
+
sql = <<-EOQ
|
137
|
+
SELECT attname
|
138
|
+
FROM pg_attribute
|
139
|
+
WHERE attrelid = #{table_id}
|
140
|
+
AND attnum = #{c}
|
141
|
+
EOQ
|
142
|
+
ActiveRecord::Base.connection.select_value(sql)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
|
168
148
|
end
|
169
149
|
end
|
@@ -5,23 +5,35 @@ module DBLeftovers
|
|
5
5
|
|
6
6
|
def initialize(constraint_name, from_table, from_column, to_table, to_column, opts={})
|
7
7
|
opts = {
|
8
|
-
:
|
9
|
-
:cascade => false
|
8
|
+
:on_delete => nil
|
10
9
|
}.merge(opts)
|
11
10
|
opts.keys.each do |k|
|
12
|
-
raise "
|
11
|
+
raise "`:set_null => true` should now be `:on_delete => :set_null`" if k.to_s == 'set_null'
|
12
|
+
raise "`:cascade => true` should now be `:on_delete => :cascade`" if k.to_s == 'cascade'
|
13
|
+
raise "Unknown option: #{k}" unless [:on_delete].include?(k)
|
13
14
|
end
|
15
|
+
raise "Unknown on_delete option: #{opts[:on_delete]}" unless [nil, :set_null, :cascade].include?(opts[:on_delete])
|
14
16
|
@constraint_name = constraint_name.to_s
|
15
17
|
@from_table = from_table.to_s
|
16
18
|
@from_column = from_column.to_s
|
17
19
|
@to_table = to_table.to_s
|
18
20
|
@to_column = to_column.to_s
|
19
21
|
|
20
|
-
@set_null = opts[:set_null
|
21
|
-
@cascade = opts[:cascade
|
22
|
+
@set_null = opts[:on_delete] == :set_null
|
23
|
+
@cascade = opts[:on_delete] == :cascade
|
22
24
|
|
23
25
|
raise "ON DELETE can't be both set_null and cascade" if @set_null and @cascade
|
24
26
|
end
|
27
|
+
|
28
|
+
def equals(other)
|
29
|
+
other.constraint_name == constraint_name and
|
30
|
+
other.from_table == from_table and
|
31
|
+
other.from_column == from_column and
|
32
|
+
other.to_table == to_table and
|
33
|
+
other.to_column == to_column and
|
34
|
+
other.opts == opts
|
35
|
+
end
|
36
|
+
|
25
37
|
end
|
26
38
|
|
27
39
|
end
|
data/spec/db_leftovers_spec.rb
CHANGED
@@ -123,8 +123,8 @@ describe DBLeftovers do
|
|
123
123
|
DBLeftovers::DatabaseInterface.starts_with
|
124
124
|
DBLeftovers::Definition.define do
|
125
125
|
foreign_key :books, :shelf_id, :shelves
|
126
|
-
foreign_key :books, :publisher_id, :publishers, :id, :
|
127
|
-
foreign_key :books, :author_id, :authors, :id, :
|
126
|
+
foreign_key :books, :publisher_id, :publishers, :id, :on_delete => :set_null
|
127
|
+
foreign_key :books, :author_id, :authors, :id, :on_delete => :cascade
|
128
128
|
end
|
129
129
|
DBLeftovers::DatabaseInterface.sqls.should have(3).items
|
130
130
|
DBLeftovers::DatabaseInterface.should have_seen_sql <<-EOQ
|
@@ -156,8 +156,8 @@ describe DBLeftovers do
|
|
156
156
|
DBLeftovers::Definition.define do
|
157
157
|
table :books do
|
158
158
|
foreign_key :shelf_id, :shelves
|
159
|
-
foreign_key :publisher_id, :publishers, :id, :
|
160
|
-
foreign_key :author_id, :authors, :id, :
|
159
|
+
foreign_key :publisher_id, :publishers, :id, :on_delete => :set_null
|
160
|
+
foreign_key :author_id, :authors, :id, :on_delete => :cascade
|
161
161
|
end
|
162
162
|
end
|
163
163
|
DBLeftovers::DatabaseInterface.sqls.should have(3).items
|
@@ -346,6 +346,59 @@ describe DBLeftovers do
|
|
346
346
|
|
347
347
|
|
348
348
|
it "should allow separating indexes and foreign keys from the same table" do
|
349
|
+
DBLeftovers::DatabaseInterface.starts_with
|
350
|
+
DBLeftovers::Definition.define do
|
351
|
+
table :books do
|
352
|
+
index :author_id
|
353
|
+
end
|
354
|
+
table :books do
|
355
|
+
foreign_key :author_id, :authors, :id
|
356
|
+
end
|
357
|
+
end
|
358
|
+
DBLeftovers::DatabaseInterface.sqls.should have(2).items
|
359
|
+
DBLeftovers::DatabaseInterface.should have_seen_sql <<-EOQ
|
360
|
+
CREATE INDEX index_books_on_author_id
|
361
|
+
ON books
|
362
|
+
(author_id)
|
363
|
+
EOQ
|
364
|
+
DBLeftovers::DatabaseInterface.should have_seen_sql <<-EOQ
|
365
|
+
ALTER TABLE books
|
366
|
+
ADD CONSTRAINT fk_books_author_id
|
367
|
+
FOREIGN KEY (author_id)
|
368
|
+
REFERENCES authors (id)
|
369
|
+
EOQ
|
370
|
+
end
|
371
|
+
|
372
|
+
it "should reject invalid foreign key options" do
|
373
|
+
lambda {
|
374
|
+
DBLeftovers::Definition.define do
|
375
|
+
foreign_key :books, :author_id, :authors, :id, :icky => :boo_boo
|
376
|
+
end
|
377
|
+
}.should raise_error(RuntimeError, "Unknown option: icky")
|
378
|
+
end
|
379
|
+
|
380
|
+
it "should reject invalid foreign key on_delete values" do
|
381
|
+
lambda {
|
382
|
+
DBLeftovers::Definition.define do
|
383
|
+
foreign_key :books, :author_id, :authors, :id, :on_delete => :panic
|
384
|
+
end
|
385
|
+
}.should raise_error(RuntimeError, "Unknown on_delete option: panic")
|
386
|
+
end
|
387
|
+
|
388
|
+
it "should give good a error message if you use the old :set_null option" do
|
389
|
+
lambda {
|
390
|
+
DBLeftovers::Definition.define do
|
391
|
+
foreign_key :books, :author_id, :authors, :id, :set_null => true
|
392
|
+
end
|
393
|
+
}.should raise_error(RuntimeError, "`:set_null => true` should now be `:on_delete => :set_null`")
|
394
|
+
end
|
395
|
+
|
396
|
+
it "should give good a error message if you use the old :cascade option" do
|
397
|
+
lambda {
|
398
|
+
DBLeftovers::Definition.define do
|
399
|
+
foreign_key :books, :author_id, :authors, :id, :cascade => true
|
400
|
+
end
|
401
|
+
}.should raise_error(RuntimeError, "`:cascade => true` should now be `:on_delete => :cascade`")
|
349
402
|
end
|
350
403
|
|
351
404
|
end
|
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.5.
|
4
|
+
version: 0.5.1
|
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: 2547372809633410828
|
143
143
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
144
|
none: false
|
145
145
|
requirements:
|