db_leftovers 0.5.0 → 0.5.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.
- 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:
|