db_leftovers 0.8.0 → 0.9.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 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: