Module: Sequel::SchemaDumper

Defined in:
lib/sequel/extensions/schema_dumper.rb

Instance Method Summary collapse

Instance Method Details

#column_schema_to_ruby_type(schema) ⇒ Object

Convert the column schema information to a hash of column options, one of which must be :type. The other options added should modify that type (e.g. :size). If a database type is not recognized, return it as a String type.



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
# File 'lib/sequel/extensions/schema_dumper.rb', line 33

def column_schema_to_ruby_type(schema)
  type = schema[:db_type].downcase
  if database_type == :oracle
    type = type.sub(/ not null\z/, '')
  end
  case type
  when /\A(medium|small)?int(?:eger)?(?:\((\d+)\))?( unsigned)?\z/
    if !$1 && $2 && $2.to_i >= 10 && $3
      # Unsigned integer type with 10 digits can potentially contain values which
      # don't fit signed integer type, so use bigint type in target database.
      {:type=>:Bignum}
    else
      {:type=>Integer}
    end
  when /\Atinyint(?:\((\d+)\))?(?: unsigned)?\z/
    {:type =>schema[:type] == :boolean ? TrueClass : Integer}
  when /\Abigint(?:\((?:\d+)\))?(?: unsigned)?\z/
    {:type=>:Bignum}
  when /\A(?:real|float|double(?: precision)?|double\(\d+,\d+\))(?: unsigned)?\z/
    {:type=>Float}
  when 'boolean', 'bit', 'bool'
    {:type=>TrueClass}
  when /\A(?:(?:tiny|medium|long|n)?text|clob)\z/
    {:type=>String, :text=>true}
  when 'date'
    {:type=>Date}
  when /\A(?:small)?datetime\z/
    {:type=>DateTime}
  when /\Atimestamp(?:\((\d+)\))?(?: with(?:out)? time zone)?\z/
    {:type=>DateTime, :size=>($1.to_i if $1)}
  when /\Atime(?: with(?:out)? time zone)?\z/
    {:type=>Time, :only_time=>true}
  when /\An?char(?:acter)?(?:\((\d+)\))?\z/
    {:type=>String, :size=>($1.to_i if $1), :fixed=>true}
  when /\A(?:n?varchar2?|character varying|bpchar|string)(?:\((\d+)\))?\z/
    {:type=>String, :size=>($1.to_i if $1)}
  when /\A(?:small)?money\z/
    {:type=>BigDecimal, :size=>[19,2]}
  when /\A(?:decimal|numeric|number)(?:\((\d+)(?:,\s*(\d+))?\))?(?: unsigned)?\z/
    s = [($1.to_i if $1), ($2.to_i if $2)].compact
    {:type=>BigDecimal, :size=>(s.empty? ? nil : s)}
  when /\A(?:bytea|(?:tiny|medium|long)?blob|(?:var)?binary)(?:\((\d+)\))?\z/
    {:type=>File, :size=>($1.to_i if $1)}
  when /\A(?:year|(?:int )?identity)\z/
    {:type=>Integer}
  else
    {:type=>String}
  end
end

#dump_foreign_key_migration(options = OPTS) ⇒ Object

Dump foreign key constraints for all tables as a migration. This complements the foreign_keys: false option to dump_schema_migration. This only dumps the constraints (not the columns) using alter_table/add_foreign_key with an array of columns.

Note that the migration this produces does not have a down block, so you cannot reverse it.



90
91
92
93
94
95
96
97
98
99
# File 'lib/sequel/extensions/schema_dumper.rb', line 90

def dump_foreign_key_migration(options=OPTS)
  ts = _dump_tables(options)
  <<END_MIG
Sequel.migration do
  change do
#{ts.map{|t| dump_table_foreign_keys(t)}.reject{|x| x == ''}.join("\n\n").gsub(/^/, '    ')}
  end
end
END_MIG
end

#dump_indexes_migration(options = OPTS) ⇒ Object

Dump indexes for all tables as a migration. This complements the indexes: false option to dump_schema_migration. Options:

:same_db

Create a dump for the same database type, so don’t ignore errors if the index statements fail.

:index_names

If set to false, don’t record names of indexes. If set to :namespace, prepend the table name to the index name if the database does not use a global index namespace.



108
109
110
111
112
113
114
115
116
117
# File 'lib/sequel/extensions/schema_dumper.rb', line 108

def dump_indexes_migration(options=OPTS)
  ts = _dump_tables(options)
  <<END_MIG
Sequel.migration do
  change do
#{ts.map{|t| dump_table_indexes(t, :add_index, options)}.reject{|x| x == ''}.join("\n\n").gsub(/^/, '    ')}
  end
end
END_MIG
end

#dump_schema_migration(options = OPTS) ⇒ Object

Return a string that contains a Sequel migration that when run would recreate the database structure. Options:

:same_db

Don’t attempt to translate database types to ruby types. If this isn’t set to true, all database types will be translated to ruby types, but there is no guarantee that the migration generated will yield the same type. Without this set, types that aren’t recognized will be translated to a string-like type.

:foreign_keys

If set to false, don’t dump foreign_keys (they can be added later via #dump_foreign_key_migration)

:indexes

If set to false, don’t dump indexes (they can be added later via #dump_index_migration).

:index_names

If set to false, don’t record names of indexes. If set to :namespace, prepend the table name to the index name.



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
# File 'lib/sequel/extensions/schema_dumper.rb', line 132

def dump_schema_migration(options=OPTS)
  options = options.dup
  if options[:indexes] == false && !options.has_key?(:foreign_keys)
    # Unless foreign_keys option is specifically set, disable if indexes
    # are disabled, as foreign keys that point to non-primary keys rely
    # on unique indexes being created first
    options[:foreign_keys] = false
  end

  ts = sort_dumped_tables(_dump_tables(options), options)
  skipped_fks = if sfk = options[:skipped_foreign_keys]
    # Handle skipped foreign keys by adding them at the end via
    # alter_table/add_foreign_key.  Note that skipped foreign keys
    # probably result in a broken down migration.
    sfka = sfk.sort.map{|table, fks| dump_add_fk_constraints(table, fks.values)}
    sfka.join("\n\n").gsub(/^/, '    ') unless sfka.empty?
  end

  <<END_MIG
Sequel.migration do
  change do
#{ts.map{|t| dump_table_schema(t, options)}.join("\n\n").gsub(/^/, '    ')}#{"\n    \n" if skipped_fks}#{skipped_fks}
  end
end
END_MIG
end

#dump_table_schema(table, options = OPTS) ⇒ Object

Return a string with a create table block that will recreate the given table’s schema. Takes the same options as dump_schema_migration.



161
162
163
164
165
# File 'lib/sequel/extensions/schema_dumper.rb', line 161

def dump_table_schema(table, options=OPTS)
  gen = dump_table_generator(table, options)
  commands = [gen.dump_columns, gen.dump_constraints, gen.dump_indexes].reject{|x| x == ''}.join("\n\n")
  "create_table(#{table.inspect}#{', :ignore_index_errors=>true' if !options[:same_db] && options[:indexes] != false && !gen.indexes.empty?}) do\n#{commands.gsub(/^/, '  ')}\nend"
end