Class: PgShrink::Table

Inherits:
Object
  • Object
show all
Defined in:
lib/pg_shrink/table.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(database, table_name, opts = {}) ⇒ Table

TODO: Figure out, do we need to be able to support tables with no keys? If so, how should we handle that?



9
10
11
12
13
14
15
16
17
# File 'lib/pg_shrink/table.rb', line 9

def initialize(database, table_name, opts = {})
  self.table_name = table_name
  self.database = database
  @opts = opts
  @filters = []
  @sanitizers = []
  @subtable_filters = []
  @subtable_sanitizers = []
end

Instance Attribute Details

#databaseObject

Returns the value of attribute database.



4
5
6
# File 'lib/pg_shrink/table.rb', line 4

def database
  @database
end

#filtersObject (readonly)

Returns the value of attribute filters.



6
7
8
# File 'lib/pg_shrink/table.rb', line 6

def filters
  @filters
end

#optsObject

Returns the value of attribute opts.



5
6
7
# File 'lib/pg_shrink/table.rb', line 5

def opts
  @opts
end

#sanitizersObject (readonly)

Returns the value of attribute sanitizers.



6
7
8
# File 'lib/pg_shrink/table.rb', line 6

def sanitizers
  @sanitizers
end

#subtable_filtersObject (readonly)

Returns the value of attribute subtable_filters.



6
7
8
# File 'lib/pg_shrink/table.rb', line 6

def subtable_filters
  @subtable_filters
end

#subtable_sanitizersObject (readonly)

Returns the value of attribute subtable_sanitizers.



6
7
8
# File 'lib/pg_shrink/table.rb', line 6

def subtable_sanitizers
  @subtable_sanitizers
end

#table_nameObject

Returns the value of attribute table_name.



3
4
5
# File 'lib/pg_shrink/table.rb', line 3

def table_name
  @table_name
end

Instance Method Details

#can_just_remove?Boolean

Returns:

  • (Boolean)


138
139
140
# File 'lib/pg_shrink/table.rb', line 138

def can_just_remove?
  self.subtable_filters.empty? && self.subtable_sanitizers.empty?
end

#condition_filter(filter) ⇒ Object



98
99
100
101
102
103
104
105
106
107
# File 'lib/pg_shrink/table.rb', line 98

def condition_filter(filter)
  self.database.log("Beginning filter on #{table_name}")
  self.database.delete_records(self.table_name, {}, filter.opts)
  self.database.log("Done filtering on #{table_name}")
  # If there aren't any subtables, there isn't much benefit to vacuuming in
  # the middle, and we'll wait until we're done with all filters
  if self.subtable_filters.any?
    self.database.vacuum_and_reindex!(self.table_name)
  end
end

#delete_records(old_records, new_records) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/pg_shrink/table.rb', line 53

def delete_records(old_records, new_records)
  if primary_key
    deleted_keys = old_records.map {|r| r[primary_key]} -
                   new_records.map {|r| r[primary_key]}
    if deleted_keys.any?
      self.database.delete_records(table_name, primary_key => deleted_keys)
    end
  else
    # TODO:  Do we need to speed this up?  Or is this an unusual enough
    # case that we can leave it slow?
    deleted_records = old_records - new_records
    deleted_records.each do |rec|
      self.database.delete_records(table_name, rec)
    end
  end
end

#filter!Object



117
118
119
120
121
122
123
124
125
126
# File 'lib/pg_shrink/table.rb', line 117

def filter!
  if remove? && can_just_remove?
    remove!
  else
    self.filters.each do |filter|
      self.condition_filter(filter)
      self.subtable_filters.each(&:propagate_table!)
    end
  end
end

#filter_by(opts) ⇒ Object



19
20
21
# File 'lib/pg_shrink/table.rb', line 19

def filter_by(opts)
  self.filters << TableFilter.new(self, opts)
end

#filter_subtable(table_name, opts = {}) {|filter.table| ... } ⇒ Object

Yields:

  • (filter.table)


23
24
25
26
27
# File 'lib/pg_shrink/table.rb', line 23

def filter_subtable(table_name, opts = {})
  filter = SubTableFilter.new(self, table_name, opts)
  self.subtable_filters << filter
  yield filter.table if block_given?
end

#filter_subtables(old_set, new_set) ⇒ Object



86
87
88
89
90
# File 'lib/pg_shrink/table.rb', line 86

def filter_subtables(old_set, new_set)
  self.subtable_filters.each do |subtable_filter|
    subtable_filter.propagate!(old_set, new_set)
  end
end

#get_records(finder_options) ⇒ Object



78
79
80
81
82
83
84
# File 'lib/pg_shrink/table.rb', line 78

def get_records(finder_options)
  if self.database
    self.database.get_records(self.table_name, finder_options)
  else
    []
  end
end

#mark_for_removal!Object

Mark @remove and add filter so that if we’re in the simple case we can just remove! and if not we can just go through filters and all dependencies will be handled



145
146
147
148
# File 'lib/pg_shrink/table.rb', line 145

def mark_for_removal!
  @remove = true
  self.filter_by 'false'
end

#primary_keyObject

Check explicitly for nil because we want to be able to set primary_key to false for e.g. join tables



160
161
162
# File 'lib/pg_shrink/table.rb', line 160

def primary_key
  opts[:primary_key].nil? ? :id : opts[:primary_key]
end

#records_in_batches(&block) ⇒ Object



70
71
72
73
74
75
76
# File 'lib/pg_shrink/table.rb', line 70

def records_in_batches(&block)
  if self.database
    self.database.records_in_batches(self.table_name, &block)
  else
    yield []
  end
end

#remove!Object



154
155
156
# File 'lib/pg_shrink/table.rb', line 154

def remove!
  self.database.delete_records(table_name, {})
end

#remove?Boolean

Returns:

  • (Boolean)


150
151
152
# File 'lib/pg_shrink/table.rb', line 150

def remove?
  !!@remove
end

#sanitize(opts = {}, &block) ⇒ Object



29
30
31
# File 'lib/pg_shrink/table.rb', line 29

def sanitize(opts = {}, &block)
  self.sanitizers << TableSanitizer.new(self, opts, &block)
end

#sanitize!Object



128
129
130
131
132
133
134
135
136
# File 'lib/pg_shrink/table.rb', line 128

def sanitize!
  self.sanitizers.each do |sanitizer|
    self.records_in_batches do |batch|
      self.sanitize_batch(batch) do |record|
        sanitizer.apply(record)
      end
    end
  end
end

#sanitize_batch(batch, &sanitize_block) ⇒ Object



109
110
111
112
113
114
115
# File 'lib/pg_shrink/table.rb', line 109

def sanitize_batch(batch, &sanitize_block)
  new_set = batch.map do |record|
    sanitize_block.call(record.dup)
  end
  update_records(batch, new_set)
  sanitize_subtables(batch, new_set)
end

#sanitize_subtable(table_name, opts = {}) {|sanitizer.table| ... } ⇒ Object

Yields:

  • (sanitizer.table)


33
34
35
36
37
# File 'lib/pg_shrink/table.rb', line 33

def sanitize_subtable(table_name, opts = {})
  sanitizer = SubTableSanitizer.new(self, table_name, opts)
  self.subtable_sanitizers << sanitizer
  yield sanitizer.table if block_given?
end

#sanitize_subtables(old_set, new_set) ⇒ Object



92
93
94
95
96
# File 'lib/pg_shrink/table.rb', line 92

def sanitize_subtables(old_set, new_set)
  self.subtable_sanitizers.each do |subtable_sanitizer|
    subtable_sanitizer.propagate!(old_set, new_set)
  end
end

#shrink!Object



164
165
166
167
# File 'lib/pg_shrink/table.rb', line 164

def shrink!
  filter!
  sanitize!
end

#update_options(opts) ⇒ Object

internal methods not intended to be used from Shrinkfile below this point



43
44
45
# File 'lib/pg_shrink/table.rb', line 43

def update_options(opts)
  @opts = @opts.merge(opts)
end

#update_records(original_records, new_records) ⇒ Object



47
48
49
50
51
# File 'lib/pg_shrink/table.rb', line 47

def update_records(original_records, new_records)
  if self.database
    database.update_records(self.table_name, original_records, new_records)
  end
end