Class: DbSubsetter::Table

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

Overview

A database in the database to be subset or imported

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, database, exporter) ⇒ Table

Returns a new instance of Table.



6
7
8
9
10
11
# File 'lib/db_subsetter/table.rb', line 6

def initialize(name, database, exporter)
  @name = name
  @exporter = exporter
  @database = database
  @full_table = @ignored = false
end

Instance Attribute Details

#nameObject

Returns the value of attribute name.



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

def name
  @name
end

Instance Method Details

#arel_tableObject



90
91
92
# File 'lib/db_subsetter/table.rb', line 90

def arel_table
  @arel_table ||= Arel::Table.new(@name)
end

#exportObject

FIXME: move the raw SQL into another class



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/db_subsetter/table.rb', line 41

def export
  print "Exporting: #{@name} (#{pages} pages)" if verbose

  rows_exported = 0
  @exporter.output.execute("CREATE TABLE #{@name.underscore} ( data TEXT )")
  0.upto(pages - 1).each do |page|
    records_for_page(page).each_slice(Exporter::INSERT_BATCH_SIZE) do |rows|
      data = rows.map { |x| @exporter.sanitize_row(@name, x) }.map(&:to_json)

      @exporter.output.execute("INSERT INTO #{@name.underscore} (data) VALUES #{Array.new(rows.size) { '(?)' }.join(',')}", data)
      rows_exported += rows.size
    end

    print '.' if verbose
  end
  puts '' if verbose
  columns = ActiveRecord::Base.connection.columns(@name).map(&:name)
  @exporter.output.execute('INSERT INTO tables VALUES (?, ?, ?)', [@name, rows_exported, columns.to_json])
end

#exportability_issuesObject



65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/db_subsetter/table.rb', line 65

def exportability_issues
  return @exportability_issues if @exportability_issues

  @exportability_issues = []
  begin
    puts "Verifying: #{@name} (#{filtered_row_count}/#{total_row_count})" if verbose
    @exportability_issues << 'Multiple pages but no primary key' if pages > 1 && primary_key.blank?
    @exportability_issues << "Too many rows (#{filtered_row_count})" if filtered_row_count > @exporter.max_filtered_rows
  rescue CircularRelationError
    @exportability_issues << 'Circular relations through this table'
  end
  @exportability_issues
end

#exportable?Boolean

Returns:

  • (Boolean)


61
62
63
# File 'lib/db_subsetter/table.rb', line 61

def exportable?
  exportability_issues.empty?
end

#filtered_idsObject



79
80
81
82
83
84
85
86
87
88
# File 'lib/db_subsetter/table.rb', line 79

def filtered_ids
  return @id_cache if @id_cache

  raise CircularRelationError if @loaded_ids
  @loaded_ids = true

  sql = filtered_records.project(:id).to_sql

  @id_cache = ActiveRecord::Base.connection.select_rows(sql).flatten
end

#filtered_row_countObject



35
36
37
38
# File 'lib/db_subsetter/table.rb', line 35

def filtered_row_count
  query = filtered_records.project(Arel.sql('count(1) AS num_rows'))
  ActiveRecord::Base.connection.select_one(query.to_sql)['num_rows'].to_i # rails-4.2+pg needs to_i
end

#ignore!Object

FIXME: these 4 methods don’t feel quite like the correct API yet



14
15
16
# File 'lib/db_subsetter/table.rb', line 14

def ignore!
  @ignored = true
end

#ignored?Boolean

Returns:

  • (Boolean)


26
27
28
# File 'lib/db_subsetter/table.rb', line 26

def ignored?
  @ignored
end

#primary_keyObject



94
95
96
# File 'lib/db_subsetter/table.rb', line 94

def primary_key
  ActiveRecord::Base.connection.primary_key(@name)
end

#relationsObject



98
99
100
# File 'lib/db_subsetter/table.rb', line 98

def relations
  ActiveRecord::Base.connection.foreign_keys(@name).map { |x| Relation.new(x, @database) }
end

#subset_in_full!Object



18
19
20
# File 'lib/db_subsetter/table.rb', line 18

def subset_in_full!
  @subset_in_full = true
end

#subset_in_full?Boolean

Returns:

  • (Boolean)


22
23
24
# File 'lib/db_subsetter/table.rb', line 22

def subset_in_full?
  @subset_in_full
end

#total_row_countObject



30
31
32
33
# File 'lib/db_subsetter/table.rb', line 30

def total_row_count
  query = arel_table.project('count(1) AS num_rows')
  ActiveRecord::Base.connection.select_one(query.to_sql)['num_rows'].to_i # rails-4.2+pg needs to_i
end