db_leftovers 0.8.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.html CHANGED
@@ -31,11 +31,11 @@ index :books, [:publisher_id, :published_at]
31
31
  index :books, :isbn, :unique => true
32
32
  </code></pre>
33
33
 
34
- <h3>foreign_key(from_table, from_column, to_table, [to_column, [opts]])</h3>
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
37
  All parameters are strings/symbols except <code>opts</code>, which is a hash.
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>.
38
+ If you omit the column names, db_leftovers will infer them based on Rails conventions. (See examples below.)
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>
@@ -47,10 +47,17 @@ The only option that is supported is <code>:on_delete</code>, which may have any
47
47
  <h4>Examples</h4>
48
48
 
49
49
  <pre><code>foreign_key :books, :author_id, :authors, :id
50
- foreign_key :books, :publisher_id, :publishers
51
50
  foreign_key :pages, :book_id, :books, :id, :on_delete =&gt; :cascade
52
51
  </code></pre>
53
52
 
53
+ <p>With implicit column names:</p>
54
+
55
+ <pre><code>foreign_key :books, :authors
56
+ foreign_key :books, :authors, :on_delete =&gt; :cascade
57
+ foreign_key :books, :co_author_id, :authors
58
+ foreign_key :books, :co_author_id, :authors, :on_delete =&gt; :cascade
59
+ </code></pre>
60
+
54
61
  <h3>check(constraint_name, on_table, expression)</h3>
55
62
 
56
63
  <p>This ensures that you have a CHECK constraint on the given table with the given name and expression.
@@ -63,7 +70,7 @@ All parameters are strings or symbols.</p>
63
70
 
64
71
  <h3>table(table_name, &amp;block)</h3>
65
72
 
66
- <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>
73
+ <p>The <code>table</code> call is just a convenience so you can group all a table's indexes etcetera together and not keep repeating the table name. You use it like this:</p>
67
74
 
68
75
  <pre><code>table :books do
69
76
  index :author_id
data/README.md CHANGED
@@ -32,11 +32,11 @@ 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(from\_table, from\_column, to\_table, [to\_column, [opts]])
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
38
  All parameters are strings/symbols except `opts`, which is a hash.
39
- If you don't pass anything for `opts`, you can leave off the `to_column` parameter, and it will default to `:id`.
39
+ If you omit the column names, db\_leftovers will infer them based on Rails conventions. (See examples below.)
40
40
  The only option that is supported is `:on_delete`, which may have any of these values:
41
41
 
42
42
  * `nil` Indicates that attempting to delete the referenced row should fail (the default).
@@ -46,9 +46,15 @@ The only option that is supported is `:on_delete`, which may have any of these v
46
46
  #### Examples
47
47
 
48
48
  foreign_key :books, :author_id, :authors, :id
49
- foreign_key :books, :publisher_id, :publishers
50
49
  foreign_key :pages, :book_id, :books, :id, :on_delete => :cascade
51
50
 
51
+ With implicit column names:
52
+
53
+ foreign_key :books, :authors
54
+ foreign_key :books, :authors, :on_delete => :cascade
55
+ foreign_key :books, :co_author_id, :authors
56
+ foreign_key :books, :co_author_id, :authors, :on_delete => :cascade
57
+
52
58
  ### check(constraint\_name, on\_table, expression)
53
59
 
54
60
  This ensures that you have a CHECK constraint on the given table with the given name and expression.
@@ -60,7 +66,7 @@ All parameters are strings or symbols.
60
66
 
61
67
  ### table(table\_name, &block)
62
68
 
63
- 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:
69
+ The `table` call is just a convenience so you can group all a table's indexes etcetera together and not keep repeating the table name. You use it like this:
64
70
 
65
71
  table :books do
66
72
  index :author_id
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.0
1
+ 0.9.1
data/db_leftovers.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "db_leftovers"
8
- s.version = "0.8.0"
8
+ s.version = "0.9.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Paul A. Jungwirth"]
@@ -101,7 +101,8 @@ module DBLeftovers
101
101
  ret = {}
102
102
  sql = <<-EOQ
103
103
  SELECT c.conname,
104
- t.relname
104
+ t.relname,
105
+ pg_get_expr(c.conbin, c.conrelid)
105
106
  FROM pg_catalog.pg_constraint c,
106
107
  pg_catalog.pg_class t,
107
108
  pg_catalog.pg_namespace n
@@ -182,7 +183,7 @@ module DBLeftovers
182
183
  end
183
184
 
184
185
  def remove_outer_parens(str)
185
- str.gsub(/^\((.*)\)$/, '\1')
186
+ str ? str.gsub(/^\((.*)\)$/, '\1') : nil
186
187
  end
187
188
 
188
189
 
@@ -38,7 +38,30 @@ module DBLeftovers
38
38
  add_index(Index.new(table_name, column_names, opts))
39
39
  end
40
40
 
41
- def foreign_key(from_table, from_column, to_table, to_column='id', opts={})
41
+ # foreign_key(from_table, [from_column], to_table, [to_column], [opts]):
42
+ # foreign_key(:books, :publishers) -> foreign_key(:books, nil, :publishers, nil)
43
+ # foreign_key(:books, :co_author_id, :authors) -> foreign_key(:books, :co_author_id, :authors, nil)
44
+ # foreign_key(:books, :publishers, opts) -> foreign_key(:books, nil, :publishers, nil, opts)
45
+ # foreign_key(:books, :co_author_id, :authors, opts) -> foreign_key(:books, :co_author_id, :authors, nil, opts)
46
+ def foreign_key(from_table, from_column=nil, to_table=nil, to_column=nil, opts={})
47
+ # First get the options hash into the right place:
48
+ if to_column.class == Hash
49
+ opts = to_column
50
+ to_column = nil
51
+ elsif to_table.class == Hash
52
+ opts = to_table
53
+ to_table = to_column = nil
54
+ end
55
+
56
+ # Sort out implicit arguments:
57
+ if from_column and not to_table and not to_column
58
+ to_table = from_column
59
+ from_column = "#{to_table.to_s.singularize}_id"
60
+ to_column = :id
61
+ elsif from_column and to_table and not to_column
62
+ to_column = :id
63
+ end
64
+
42
65
  add_foreign_key(ForeignKey.new(name_constraint(from_table, from_column), from_table, from_column, to_table, to_column, opts))
43
66
  end
44
67
 
@@ -57,10 +80,22 @@ module DBLeftovers
57
80
  when STATUS_CHANGED
58
81
  @db.execute_drop_index(idx.table_name, idx.index_name)
59
82
  @db.execute_add_index(idx)
60
- puts "Dropped & re-created index: #{idx.index_name} on #{idx.table_name}"
83
+ if idx.where_clause
84
+ # NB: This is O(n*m) where n is your indexes and m is your indexes with WHERE clauses.
85
+ # But it's hard to believe it matters:
86
+ new_idx = @db.lookup_all_indexes[truncate_index_name(idx.index_name)]
87
+ puts "Dropped & re-created index: #{idx.index_name} on #{idx.table_name} WHERE #{new_idx.where_clause}"
88
+ else
89
+ puts "Dropped & re-created index: #{idx.index_name} on #{idx.table_name}"
90
+ end
61
91
  when STATUS_NEW
62
92
  @db.execute_add_index(idx)
63
- puts "Created index: #{idx.index_name} on #{idx.table_name}"
93
+ if idx.where_clause
94
+ new_idx = @db.lookup_all_indexes[truncate_index_name(idx.index_name)]
95
+ puts "Created index: #{idx.index_name} on #{idx.table_name} WHERE #{new_idx.where_clause}"
96
+ else
97
+ puts "Created index: #{idx.index_name} on #{idx.table_name}"
98
+ end
64
99
  end
65
100
  @new_indexes[truncate_index_name(idx.index_name)] = table_name
66
101
  end
@@ -114,10 +149,14 @@ module DBLeftovers
114
149
  when STATUS_CHANGED
115
150
  @db.execute_drop_constraint(chk.constraint_name, chk.on_table)
116
151
  @db.execute_add_constraint(chk)
117
- puts "Dropped & re-created CHECK constraint: #{chk.constraint_name} on #{chk.on_table} as #{chk.check}"
152
+ # NB: This is O(n^2) where n is your check constraints.
153
+ # But it's hard to believe it matters:
154
+ new_chk = @db.lookup_all_constraints[chk.constraint_name]
155
+ puts "Dropped & re-created CHECK constraint: #{chk.constraint_name} on #{chk.on_table} as #{new_chk.check}"
118
156
  when STATUS_NEW
119
157
  @db.execute_add_constraint(chk)
120
- puts "Created CHECK constraint: #{chk.constraint_name} on #{chk.on_table}"
158
+ new_chk = @db.lookup_all_constraints[chk.constraint_name]
159
+ puts "Created CHECK constraint: #{chk.constraint_name} on #{chk.on_table} as #{new_chk.check}"
121
160
  end
122
161
  @new_constraints[chk.constraint_name] = chk
123
162
  end
@@ -14,7 +14,7 @@ module DBLeftovers
14
14
  @dsl.index(@table_name, column_names, opts)
15
15
  end
16
16
 
17
- def foreign_key(from_column, to_table, to_column='id', opts={})
17
+ def foreign_key(from_column=nil, to_table=nil, to_column=nil, opts={})
18
18
  @dsl.foreign_key(@table_name, from_column, to_table, to_column, opts)
19
19
  end
20
20
 
@@ -187,7 +187,43 @@ describe DBLeftovers do
187
187
  EOQ
188
188
  end
189
189
 
190
+ it "should create foreign keys with optional params inferred" do
191
+ DBLeftovers::DatabaseInterface.starts_with
192
+ DBLeftovers::Definition.define do
193
+ foreign_key :books, :shelves
194
+ foreign_key :books, :publishers, :on_delete => :set_null
195
+ foreign_key :books, :publication_country_id, :countries
196
+ foreign_key :books, :co_author_id, :authors, :on_delete => :cascade
197
+ end
198
+ DBLeftovers::DatabaseInterface.sqls.should have(4).items
199
+ DBLeftovers::DatabaseInterface.should have_seen_sql <<-EOQ
200
+ ALTER TABLE books ADD CONSTRAINT fk_books_shelf_id FOREIGN KEY (shelf_id) REFERENCES shelves (id)
201
+ EOQ
202
+ DBLeftovers::DatabaseInterface.should have_seen_sql <<-EOQ
203
+ ALTER TABLE books ADD CONSTRAINT fk_books_publisher_id FOREIGN KEY (publisher_id) REFERENCES publishers (id) ON DELETE SET NULL
204
+ EOQ
205
+ DBLeftovers::DatabaseInterface.should have_seen_sql <<-EOQ
206
+ ALTER TABLE books ADD CONSTRAINT fk_books_publication_country_id
207
+ FOREIGN KEY (publication_country_id) REFERENCES countries (id)
208
+ EOQ
209
+ DBLeftovers::DatabaseInterface.should have_seen_sql <<-EOQ
210
+ ALTER TABLE books ADD CONSTRAINT fk_books_co_author_id
211
+ FOREIGN KEY (co_author_id) REFERENCES authors (id) ON DELETE CASCADE
212
+ EOQ
213
+ end
190
214
 
215
+ it "should create foreign keys with optional params inferred and table block" do
216
+ DBLeftovers::DatabaseInterface.starts_with
217
+ DBLeftovers::Definition.define do
218
+ table :books do
219
+ foreign_key :shelves
220
+ foreign_key :publishers
221
+ foreign_key :publication_country_id, :countries
222
+ foreign_key :co_author_id, :authors, :on_delete => :cascade
223
+ end
224
+ end
225
+ DBLeftovers::DatabaseInterface.sqls.should have(4).items
226
+ end
191
227
 
192
228
  it "should not create indexes when they already exist" do
193
229
  DBLeftovers::DatabaseInterface.starts_with([
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.8.0
4
+ version: 0.9.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: 856836431
142
+ hash: 712708189
143
143
  required_rubygems_version: !ruby/object:Gem::Requirement
144
144
  none: false
145
145
  requirements: