Module: ActiveRecord::MTI::ConnectionAdapters::PostgreSQL::SchemaStatements

Defined in:
lib/active_record/mti/connection_adapters/postgresql/schema_statements.rb

Instance Method Summary collapse

Instance Method Details

#create_table(table_name, options = {}) {|td| ... } ⇒ Object

Creates a new table with the name table_name. table_name may either be a String or a Symbol.

Add :inherits options for Postgres table inheritance. If a table is inherited then the primary key column is also inherited. Therefore the :primary_key options is set to false so we don’t duplicate that colume.

However the primary key column from the parent is not inherited as primary key so we manually add it. Lastly we also create indexes on the child table to match those on the parent table since indexes are also not inherited.

Yields:

  • (td)


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/active_record/mti/connection_adapters/postgresql/schema_statements.rb', line 18

def create_table(table_name, options = {})
  if options[:inherits]
    options[:id] = false
    options.delete(:primary_key)
  end

  if schema = options.delete(:schema)
    # If we specify a schema then we only create it if it doesn't exist
    # and we only force create it if only the specific schema is in the search path
    table_name = %Q("#{schema}"."#{table_name}")
  end

  if parent_table = options.delete(:inherits)
    options[:options] = [%Q(INHERITS ("#{parent_table}")), options[:options]].compact.join
  end

  td = create_table_definition table_name, options[:temporary], options[:options], options[:as]

  if options[:id] != false && !options[:as]
    pk = options.fetch(:primary_key) do
      Base.get_primary_key table_name.to_s.singularize
    end

    if pk.is_a?(Array)
      td.primary_keys pk
    else
      td.primary_key pk, options.fetch(:id, :primary_key), options
    end
  end

  yield td if block_given?

  if options[:force] && data_source_exists?(table_name)
    drop_table(table_name, options)
  end

  # Rails 5 wont create an empty column list which we might have if we're
  # working with inherited tables.  So we need to do that manually
  sql = schema_creation.accept(td)
  # sql = sql.sub("INHERITS", "() INHERITS") if td.columns.empty?

  result = execute sql

  if parent_table
    parent_table_primary_key = primary_key(parent_table)
    execute %Q(ALTER TABLE "#{table_name}" ADD PRIMARY KEY ("#{parent_table_primary_key}"))


    indexes(parent_table).each do |index|
      attributes = index.to_h.slice(:unique, :using, :where, :orders)

      # Why rails insists on being inconsistant with itself is beyond me.
      attributes[:order] = attributes.delete(:orders)

      add_index table_name, index.columns, attributes
    end
    # triggers_for_table(parent_table).each do |trigger|
    #   name = trigger.first
    #   definition = trigger.second.merge(on: table_name)
    #   create_trigger name, definition
    # end
  end

  td.indexes.each_pair { |c,o| add_index table_name, c, o }
end

#parent_table(table_name) ⇒ Object



96
97
98
99
# File 'lib/active_record/mti/connection_adapters/postgresql/schema_statements.rb', line 96

def parent_table(table_name)
  parents = parent_tables(table_name)
  parents.first
end

#parent_tables(table_name) ⇒ Object

Parent of inherited table



85
86
87
88
89
90
91
92
93
94
# File 'lib/active_record/mti/connection_adapters/postgresql/schema_statements.rb', line 85

def parent_tables(table_name)
  result = exec_query(<<-SQL, "SCHEMA")
    SELECT pg_namespace.nspname, pg_class.relname
    FROM pg_catalog.pg_inherits
      INNER JOIN pg_catalog.pg_class ON (pg_inherits.inhparent = pg_class.oid)
      INNER JOIN pg_catalog.pg_namespace ON (pg_class.relnamespace = pg_namespace.oid)
    WHERE inhrelid = '#{table_name}'::regclass
  SQL
  result.map{|a| a['relname']}
end