Skip to content
This repository
tree: faeca694b3
Fetching contributors…

Cannot retrieve contributors at this time

file 232 lines (197 sloc) 8.795 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
require "cases/helper"
require 'stringio'


class SchemaDumperTest < ActiveRecord::TestCase
  def standard_dump
    stream = StringIO.new
    ActiveRecord::SchemaDumper.ignore_tables = []
    ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
    stream.string
  end

  def test_schema_dump
    output = standard_dump
    assert_match %r{create_table "accounts"}, output
    assert_match %r{create_table "authors"}, output
    assert_no_match %r{create_table "schema_migrations"}, output
  end

  def test_schema_dump_excludes_sqlite_sequence
    output = standard_dump
    assert_no_match %r{create_table "sqlite_sequence"}, output
  end

  def test_schema_dump_includes_camelcase_table_name
    output = standard_dump
    assert_match %r{create_table "CamelCase"}, output
  end

  def assert_line_up(lines, pattern, required = false)
    return assert(true) if lines.empty?
    matches = lines.map { |line| line.match(pattern) }
    assert matches.all? if required
    matches.compact!
    return assert(true) if matches.empty?
    assert_equal 1, matches.map{ |match| match.offset(0).first }.uniq.length
  end

  def column_definition_lines(output = standard_dump)
    output.scan(/^( *)create_table.*?\n(.*?)^\1end/m).map{ |m| m.last.split(/\n/) }
  end

  def test_types_line_up
    column_definition_lines.each do |column_set|
      next if column_set.empty?

      lengths = column_set.map do |column|
        if match = column.match(/t\.(?:integer|decimal|float|datetime|timestamp|time|date|text|binary|string|boolean|primary_key)\s+"/)
          match[0].length
        end
      end

      assert_equal 1, lengths.uniq.length
    end
  end

  def test_arguments_line_up
    column_definition_lines.each do |column_set|
      assert_line_up(column_set, /:default => /)
      assert_line_up(column_set, /:limit => /)
      assert_line_up(column_set, /:null => /)
    end
  end

  def test_no_dump_errors
    output = standard_dump
    assert_no_match %r{\# Could not dump table}, output
  end

  def test_schema_dump_includes_not_null_columns
    stream = StringIO.new

    ActiveRecord::SchemaDumper.ignore_tables = [/^[^r]/]
    ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
    output = stream.string
    assert_match %r{:null => false}, output
  end

  def test_schema_dump_includes_limit_constraint_for_integer_columns
    stream = StringIO.new

    ActiveRecord::SchemaDumper.ignore_tables = [/^(?!integer_limits)/]
    ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
    output = stream.string

    if current_adapter?(:PostgreSQLAdapter)
      assert_match %r{c_int_1.*:limit => 2}, output
      assert_match %r{c_int_2.*:limit => 2}, output

      # int 3 is 4 bytes in postgresql
      assert_match %r{c_int_3.*}, output
      assert_no_match %r{c_int_3.*:limit}, output

      assert_match %r{c_int_4.*}, output
      assert_no_match %r{c_int_4.*:limit}, output
    elsif current_adapter?(:MysqlAdapter)
      assert_match %r{c_int_1.*:limit => 1}, output
      assert_match %r{c_int_2.*:limit => 2}, output
      assert_match %r{c_int_3.*:limit => 3}, output

      assert_match %r{c_int_4.*}, output
      assert_no_match %r{c_int_4.*:limit}, output
    elsif current_adapter?(:SQLiteAdapter)
      assert_match %r{c_int_1.*:limit => 1}, output
      assert_match %r{c_int_2.*:limit => 2}, output
      assert_match %r{c_int_3.*:limit => 3}, output
      assert_match %r{c_int_4.*:limit => 4}, output
    end
    assert_match %r{c_int_without_limit.*}, output
    assert_no_match %r{c_int_without_limit.*:limit}, output

    if current_adapter?(:SQLiteAdapter)
      assert_match %r{c_int_5.*:limit => 5}, output
      assert_match %r{c_int_6.*:limit => 6}, output
      assert_match %r{c_int_7.*:limit => 7}, output
      assert_match %r{c_int_8.*:limit => 8}, output
    elsif current_adapter?(:OracleAdapter)
      assert_match %r{c_int_5.*:limit => 5}, output
      assert_match %r{c_int_6.*:limit => 6}, output
      assert_match %r{c_int_7.*:limit => 7}, output
      assert_match %r{c_int_8.*:limit => 8}, output
    else
      assert_match %r{c_int_5.*:limit => 8}, output
      assert_match %r{c_int_6.*:limit => 8}, output
      assert_match %r{c_int_7.*:limit => 8}, output
      assert_match %r{c_int_8.*:limit => 8}, output
    end
  end

  def test_schema_dump_with_string_ignored_table
    stream = StringIO.new

    ActiveRecord::SchemaDumper.ignore_tables = ['accounts']
    ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
    output = stream.string
    assert_no_match %r{create_table "accounts"}, output
    assert_match %r{create_table "authors"}, output
    assert_no_match %r{create_table "schema_migrations"}, output
  end

  def test_schema_dump_with_regexp_ignored_table
    stream = StringIO.new

    ActiveRecord::SchemaDumper.ignore_tables = [/^account/]
    ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
    output = stream.string
    assert_no_match %r{create_table "accounts"}, output
    assert_match %r{create_table "authors"}, output
    assert_no_match %r{create_table "schema_migrations"}, output
  end

  def test_schema_dump_illegal_ignored_table_value
    stream = StringIO.new
    ActiveRecord::SchemaDumper.ignore_tables = [5]
    assert_raise(StandardError) do
      ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
    end
  end

  def test_schema_dumps_index_columns_in_right_order
    index_definition = standard_dump.split(/\n/).grep(/add_index.*companies/).first.strip
    assert_equal 'add_index "companies", ["firm_id", "type", "rating", "ruby_type"], :name => "company_index"', index_definition
  end

  def test_schema_dump_should_honor_nonstandard_primary_keys
    output = standard_dump
    match = output.match(%r{create_table "movies"(.*)do})
    assert_not_nil(match, "nonstandardpk table not found")
    assert_match %r(:primary_key => "movieid"), match[1], "non-standard primary key not preserved"
  end

  if current_adapter?(:MysqlAdapter)
    def test_schema_dump_should_not_add_default_value_for_mysql_text_field
      output = standard_dump
      assert_match %r{t.text\s+"body",\s+:null => false$}, output
    end

    def test_schema_dump_includes_length_for_mysql_blob_and_text_fields
      output = standard_dump
      assert_match %r{t.binary\s+"tiny_blob",\s+:limit => 255$}, output
      assert_match %r{t.binary\s+"normal_blob"$}, output
      assert_match %r{t.binary\s+"medium_blob",\s+:limit => 16777215$}, output
      assert_match %r{t.binary\s+"long_blob",\s+:limit => 2147483647$}, output
      assert_match %r{t.text\s+"tiny_text",\s+:limit => 255$}, output
      assert_match %r{t.text\s+"normal_text"$}, output
      assert_match %r{t.text\s+"medium_text",\s+:limit => 16777215$}, output
      assert_match %r{t.text\s+"long_text",\s+:limit => 2147483647$}, output
    end

    def test_mysql_schema_dump_should_honor_primary_keys_limits
      output = standard_dump
      match = output.match(%r{create_table "primary_key_limit",.*?:id => false\b.*? do (.*?)\bend$}m)
      assert_not_nil(match, output)
      assert_match %r(t.primary_key\s+"id",\s+:limit => \d+$), match[1], "limit option not found on primary key"
    end
  end

  def test_schema_dump_includes_decimal_options
    stream = StringIO.new
    ActiveRecord::SchemaDumper.ignore_tables = [/^[^n]/]
    ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
    output = stream.string
    assert_match %r{:precision => 3,[[:space:]]+:scale => 2,[[:space:]]+:default => 2.78}, output
  end

  if current_adapter?(:PostgreSQLAdapter)
    def test_schema_dump_includes_xml_shorthand_definition
      output = standard_dump
      if %r{create_table "postgresql_xml_data_type"} =~ output
        assert_match %r{t.xml "data"}, output
      end
    end
  end

  def test_schema_dump_keeps_large_precision_integer_columns_as_decimal
    output = standard_dump
    # Oracle supports precision up to 38 and it identifies decimals with scale 0 as integers
    if current_adapter?(:OracleAdapter)
      assert_match %r{t.integer\s+"atoms_in_universe",\s+:precision => 38,\s+:scale => 0}, output
    else
      assert_match %r{t.decimal\s+"atoms_in_universe",\s+:limit => 55,\s+:precision => 55,\s+:scale => 0}, output
    end
  end

  def test_schema_dump_keeps_id_column_when_id_is_false_and_id_column_added
    output = standard_dump
    match = output.match(%r{create_table "goofy_string_id"(.*)do.*\n(.*)\n})
    assert_not_nil(match, "goofy_string_id table not found")
    assert_match %r(:id => false), match[1], "no table id not preserved"
    assert_match %r{t.string[[:space:]]+"id",[[:space:]]+:null => false$}, match[2], "non-primary key id column not preserved"
  end
end
Something went wrong with that request. Please try again.