Class: PgMorph::Polymorphic

Inherits:
Object
  • Object
show all
Includes:
Naming
Defined in:
lib/pg_morph/polymorphic.rb

Constant Summary collapse

BASE_TABLE_SUFIX =
:base

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Naming

#before_insert_fun_name, #before_insert_trigger_name, #column_name_id, #column_name_type, #proxy_table, #type

Constructor Details

#initialize(parent_table, child_table, options) ⇒ Polymorphic

Returns a new instance of Polymorphic.

Raises:



9
10
11
12
13
14
15
16
# File 'lib/pg_morph/polymorphic.rb', line 9

def initialize(parent_table, child_table, options)
  @parent_table = parent_table
  @child_table = child_table
  @column_name = options[:column]
  @base_table = options[:base_table] || :"#{parent_table}_#{BASE_TABLE_SUFIX}"

  raise PgMorph::Exception.new("Column not specified") unless @column_name
end

Instance Attribute Details

#base_tableObject (readonly)

Returns the value of attribute base_table.



7
8
9
# File 'lib/pg_morph/polymorphic.rb', line 7

def base_table
  @base_table
end

#child_tableObject (readonly)

Returns the value of attribute child_table.



7
8
9
# File 'lib/pg_morph/polymorphic.rb', line 7

def child_table
  @child_table
end

#column_nameObject (readonly)

Returns the value of attribute column_name.



7
8
9
# File 'lib/pg_morph/polymorphic.rb', line 7

def column_name
  @column_name
end

#parent_tableObject (readonly)

Returns the value of attribute parent_table.



7
8
9
# File 'lib/pg_morph/polymorphic.rb', line 7

def parent_table
  @parent_table
end

Instance Method Details

#can_rename_to_base_table?Boolean

Returns:

  • (Boolean)

Raises:



25
26
27
28
29
30
31
32
33
34
35
# File 'lib/pg_morph/polymorphic.rb', line 25

def can_rename_to_base_table?
  return true unless ActiveRecord::Base.connection.table_exists? base_table

  parent_table_set = ActiveRecord::Base.connection.columns(parent_table).
                      map{|column| column.as_json.except('null')}
  base_table_set = ActiveRecord::Base.connection.columns(base_table).
                      map{|column| column.as_json.except('null')}

  return false if parent_table_set == base_table_set
  raise PgMorph::Exception.new('table name mismatch!')
end

#create_base_table_view_sqlObject



37
38
39
40
41
# File 'lib/pg_morph/polymorphic.rb', line 37

def create_base_table_view_sql
  %Q{
    CREATE OR REPLACE VIEW #{parent_table} AS SELECT * FROM #{base_table};
  }
end

#create_before_insert_trigger_fun_sqlObject



53
54
55
56
57
58
59
60
61
62
# File 'lib/pg_morph/polymorphic.rb', line 53

def create_before_insert_trigger_fun_sql
  before_insert_trigger_content do
    %Q{
    IF NEW.id IS NULL THEN
      NEW.id := nextval('#{parent_table}_id_seq');
    END IF;
    #{create_trigger_body.strip}
    }
  end
end

#create_before_insert_trigger_sqlObject



64
65
66
67
68
69
# File 'lib/pg_morph/polymorphic.rb', line 64

def create_before_insert_trigger_sql
  fun_name = before_insert_fun_name
  trigger_name = before_insert_trigger_name

  create_trigger_sql(parent_table, trigger_name, fun_name, 'INSTEAD OF INSERT')
end

#create_proxy_table_sqlObject



43
44
45
46
47
48
49
50
51
# File 'lib/pg_morph/polymorphic.rb', line 43

def create_proxy_table_sql
  %Q{
  CREATE TABLE #{proxy_table} (
    CHECK (#{column_name_type} = '#{type}'),
    PRIMARY KEY (id),
    FOREIGN KEY (#{column_name_id}) REFERENCES #{child_table}(id)
  ) INHERITS (#{base_table});
  }
end

#remove_base_table_view_sqlObject



99
100
101
102
103
104
105
# File 'lib/pg_morph/polymorphic.rb', line 99

def remove_base_table_view_sql
  if check_more_partitions.present?
    ''
  else
    %Q{ DROP VIEW #{parent_table}; }
  end
end

#remove_before_insert_trigger_sqlObject



71
72
73
74
75
76
77
78
79
80
81
# File 'lib/pg_morph/polymorphic.rb', line 71

def remove_before_insert_trigger_sql
  trigger_name = before_insert_trigger_name
  fun_name = before_insert_fun_name
  cleared = check_more_partitions

  if cleared.present?
    update_before_insert_trigger_sql(cleared)
  else
    drop_trigger_and_fun_sql(trigger_name, parent_table, fun_name)
  end
end

#remove_proxy_tableObject



90
91
92
93
94
95
96
97
# File 'lib/pg_morph/polymorphic.rb', line 90

def remove_proxy_table
  table_empty = ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM #{parent_table}_#{child_table}").to_i.zero?
  if table_empty
    %Q{ DROP TABLE IF EXISTS #{proxy_table}; }
  else
    raise PG::Error.new("Partition table #{proxy_table} contains data.\nRemove them before if you want to drop that table.\n")
  end
end

#rename_base_table_back_sqlObject



107
108
109
110
111
112
113
# File 'lib/pg_morph/polymorphic.rb', line 107

def rename_base_table_back_sql
  if check_more_partitions.present?
    ''
  else
    %Q{ ALTER TABLE #{base_table} RENAME TO #{parent_table}; }
  end
end

#rename_base_table_sqlObject



18
19
20
21
22
23
# File 'lib/pg_morph/polymorphic.rb', line 18

def rename_base_table_sql
  return '' unless can_rename_to_base_table?
  %Q{
    ALTER TABLE #{parent_table} RENAME TO #{base_table};
  }
end

#update_before_insert_trigger_sql(cleared) ⇒ Object



83
84
85
86
87
88
# File 'lib/pg_morph/polymorphic.rb', line 83

def update_before_insert_trigger_sql(cleared)
  cleared[0][0].sub!('ELSIF', 'IF')
  before_insert_trigger_content do
    cleared.map { |m| m[0] }.join('').strip
  end
end