db_leftovers 1.3.3 → 1.4.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/Changelog +6 -0
- data/README.md +5 -1
- data/lib/db_leftovers/generic_database_interface.rb +1 -1
- data/lib/db_leftovers/index.rb +25 -4
- data/lib/db_leftovers/postgres_database_interface.rb +7 -3
- data/lib/db_leftovers/version.rb +1 -1
- data/spec/postgres_spec.rb +16 -0
- metadata +3 -2
data/Changelog
ADDED
data/README.md
CHANGED
@@ -44,7 +44,7 @@ Within the DSL file, the following methods are supported:
|
|
44
44
|
|
45
45
|
### index(table\_name, columns, [opts])
|
46
46
|
|
47
|
-
This ensures that you have an index on the given table and column(s). The `columns` parameter can be either a
|
47
|
+
This ensures that you have an index on the given table and column(s). The `columns` parameter can be either a symbol or a list of strings/symbols. (If you pass a single string for the `columns` parameter, it will be treated as the expression for a functional index rather than a column name.) Opts is a hash with the following possible keys:
|
48
48
|
|
49
49
|
* `:name` The name of the index. Defaults to `index_`*table\_name*`_on_`*column\_names*, like the `add_index` method from Rails migrations.
|
50
50
|
|
@@ -54,11 +54,15 @@ This ensures that you have an index on the given table and column(s). The `colum
|
|
54
54
|
|
55
55
|
* `:using` Lets you specify what kind of index to create. Default is `btree`, but if you're on Postgres you might also want `gist`, `gin`, or `hash`.
|
56
56
|
|
57
|
+
* `:function` Lets you specify an expression rather than a list of columns. If you give this option, you should pass an empty list of column names. Alternately, you can pass a string as the column name (rather than a symbol), and db\_leftovers will interpret it as a function.
|
58
|
+
|
57
59
|
#### Examples
|
58
60
|
|
59
61
|
index :books, :author_id
|
60
62
|
index :books, [:publisher_id, :published_at]
|
61
63
|
index :books, :isbn, :unique => true
|
64
|
+
index :authors, [], function: 'lower(name)'
|
65
|
+
index :authors, 'lower(name)'
|
62
66
|
|
63
67
|
### foreign\_key(from\_table, [from\_column], to\_table, [to\_column], [opts])
|
64
68
|
|
data/lib/db_leftovers/index.rb
CHANGED
@@ -3,23 +3,33 @@ module DBLeftovers
|
|
3
3
|
# Just a struct to hold all the info for one index:
|
4
4
|
class Index
|
5
5
|
attr_accessor :table_name, :column_names, :index_name,
|
6
|
-
:where_clause, :using_clause, :unique
|
6
|
+
:where_clause, :using_clause, :unique, :index_function
|
7
7
|
|
8
8
|
def initialize(table_name, column_names, opts={})
|
9
9
|
opts = {
|
10
10
|
:where => nil,
|
11
|
+
:function => nil,
|
11
12
|
:unique => false,
|
12
13
|
:using => nil
|
13
14
|
}.merge(opts)
|
14
15
|
opts.keys.each do |k|
|
15
|
-
raise "Unknown option: #{k}" unless [:where, :unique, :using, :name].include?(k)
|
16
|
+
raise "Unknown option: #{k}" unless [:where, :function, :unique, :using, :name].include?(k)
|
17
|
+
end
|
18
|
+
if column_names.is_a?(String) and opts[:function].nil?
|
19
|
+
opts[:function] = column_names
|
20
|
+
column_names = []
|
16
21
|
end
|
17
22
|
@table_name = table_name.to_s
|
18
23
|
@column_names = [column_names].flatten.map{|x| x.to_s}
|
19
24
|
@where_clause = opts[:where]
|
25
|
+
@index_function = opts[:function]
|
20
26
|
@using_clause = opts[:using]
|
21
27
|
@unique = !!opts[:unique]
|
22
28
|
@index_name = (opts[:name] || choose_name(@table_name, @column_names)).to_s
|
29
|
+
|
30
|
+
raise "Indexes need a table!" unless @table_name
|
31
|
+
raise "Indexes need at least column or an expression!" unless (@column_names.any? or @index_function)
|
32
|
+
raise "Can't have both columns and an expression!" if (@column_names.size > 0 and @index_function)
|
23
33
|
end
|
24
34
|
|
25
35
|
def unique?
|
@@ -31,19 +41,30 @@ module DBLeftovers
|
|
31
41
|
other.column_names == column_names and
|
32
42
|
other.index_name == index_name and
|
33
43
|
other.where_clause == where_clause and
|
44
|
+
other.index_function == index_function and
|
34
45
|
other.using_clause == using_clause and
|
35
46
|
other.unique == unique
|
36
47
|
end
|
37
48
|
|
38
49
|
def to_s
|
39
|
-
"<#{@index_name}: #{@table_name}.[#{column_names.join(",")}] unique=#{@unique}, where=#{@where_clause}, using=#{@using_clause}>"
|
50
|
+
"<#{@index_name}: #{@table_name}.[#{column_names.join(",")}] unique=#{@unique}, where=#{@where_clause}, function=#{@index_function}, using=#{@using_clause}>"
|
40
51
|
end
|
41
52
|
|
42
53
|
private
|
43
54
|
|
44
55
|
def choose_name(table_name, column_names)
|
56
|
+
topic = if column_names.any?
|
57
|
+
column_names.join("_and_")
|
58
|
+
else
|
59
|
+
index_function
|
60
|
+
end
|
61
|
+
ret = "index_#{table_name}_on_#{topic}"
|
62
|
+
ret = ret.gsub(/[^a-zA-Z0-9]/, '_').
|
63
|
+
gsub(/__+/, '_').
|
64
|
+
gsub(/^_/, '').
|
65
|
+
gsub(/_$/, '')
|
45
66
|
# Max length in Postgres is 63; in MySQL 64:
|
46
|
-
|
67
|
+
ret[0,63]
|
47
68
|
end
|
48
69
|
|
49
70
|
end
|
@@ -16,7 +16,8 @@ module DBLeftovers
|
|
16
16
|
ix.indisunique AS is_unique,
|
17
17
|
array_to_string(ix.indkey, ',') AS column_numbers,
|
18
18
|
am.amname AS index_type,
|
19
|
-
pg_get_expr(ix.indpred, ix.indrelid) AS where_clause
|
19
|
+
pg_get_expr(ix.indpred, ix.indrelid) AS where_clause,
|
20
|
+
pg_get_expr(ix.indexprs, ix.indrelid) AS index_function
|
20
21
|
FROM pg_class t,
|
21
22
|
pg_class i,
|
22
23
|
pg_index ix,
|
@@ -37,10 +38,11 @@ module DBLeftovers
|
|
37
38
|
ix.indrelid,
|
38
39
|
ix.indkey,
|
39
40
|
am.amname,
|
40
|
-
ix.indpred
|
41
|
+
ix.indpred,
|
42
|
+
ix.indexprs
|
41
43
|
ORDER BY t.relname, i.relname
|
42
44
|
EOQ
|
43
|
-
@conn.select_rows(sql).each do |indexrelid, indrelid, table_name, index_name, is_unique, column_numbers, index_method, where_clause|
|
45
|
+
@conn.select_rows(sql).each do |indexrelid, indrelid, table_name, index_name, is_unique, column_numbers, index_method, where_clause, index_function|
|
44
46
|
where_clause = remove_outer_parens(where_clause) if where_clause
|
45
47
|
index_method = nil if index_method == 'btree'
|
46
48
|
ret[index_name] = Index.new(
|
@@ -48,6 +50,7 @@ module DBLeftovers
|
|
48
50
|
column_names_for_index(indrelid, column_numbers.split(",")),
|
49
51
|
unique: is_unique == 't',
|
50
52
|
where: where_clause,
|
53
|
+
function: index_function,
|
51
54
|
using: index_method,
|
52
55
|
name: index_name
|
53
56
|
)
|
@@ -128,6 +131,7 @@ module DBLeftovers
|
|
128
131
|
private
|
129
132
|
|
130
133
|
def column_names_for_index(table_id, column_numbers)
|
134
|
+
return [] if column_numbers == ['0']
|
131
135
|
column_numbers.map do |c|
|
132
136
|
sql = <<-EOQ
|
133
137
|
SELECT attname
|
data/lib/db_leftovers/version.rb
CHANGED
data/spec/postgres_spec.rb
CHANGED
@@ -102,6 +102,22 @@ describe DBLeftovers::PostgresDatabaseInterface do
|
|
102
102
|
@db.lookup_all_constraints['books_have_positive_pages'].check.should == 'pages_count > 12'
|
103
103
|
end
|
104
104
|
|
105
|
+
it "should allow functional indexes, specified as a string" do
|
106
|
+
DBLeftovers::Definition.define :db_interface => @db do
|
107
|
+
index :authors, 'lower(name)'
|
108
|
+
end
|
109
|
+
@db.lookup_all_indexes.size.should == 1
|
110
|
+
@db.lookup_all_indexes.keys.sort.should == ['index_authors_on_lower_name']
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should allow functional indexes, specified with an option" do
|
114
|
+
DBLeftovers::Definition.define :db_interface => @db do
|
115
|
+
index :authors, [], function: 'lower(name)'
|
116
|
+
end
|
117
|
+
@db.lookup_all_indexes.size.should == 1
|
118
|
+
@db.lookup_all_indexes.keys.sort.should == ['index_authors_on_lower_name']
|
119
|
+
end
|
120
|
+
|
105
121
|
end
|
106
122
|
end
|
107
123
|
|
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: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -69,6 +69,7 @@ extra_rdoc_files: []
|
|
69
69
|
files:
|
70
70
|
- .document
|
71
71
|
- .gitignore
|
72
|
+
- Changelog
|
72
73
|
- Gemfile
|
73
74
|
- Gemfile.lock
|
74
75
|
- LICENSE.txt
|
@@ -111,7 +112,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
111
112
|
version: '0'
|
112
113
|
segments:
|
113
114
|
- 0
|
114
|
-
hash:
|
115
|
+
hash: 1649859164079023412
|
115
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
117
|
none: false
|
117
118
|
requirements:
|