Module: ActiveRecord::ConnectionAdapters::Fb::SchemaStatements

Included in:
ActiveRecord::ConnectionAdapters::FbAdapter
Defined in:
lib/active_record/connection_adapters/fb/schema_statements.rb

Instance Method Summary collapse

Instance Method Details

#add_column(table_name, column_name, type, options = {}) ⇒ Object

Adds a new column to the named table. See TableDefinition#column for details of the options you can use.



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 113

def add_column(table_name, column_name, type, options = {})
  while_ensuring_boolean_domain { super }

  if type == :primary_key && options[:sequence] != false
    create_sequence(options[:sequence] || default_sequence_name(table_name))
  end

  return unless options[:position]
  # position is 1-based but add 1 to skip id column
  execute(squish_sql(<<-end_sql))
    ALTER TABLE #{quote_table_name(table_name)}
    ALTER COLUMN #{quote_column_name(column_name)}
    POSITION #{options[:position] + 1}
  end_sql
end

#change_column(table_name, column_name, type, options = {}) ⇒ Object

Changes the column’s definition according to the new options. See TableDefinition#column for details of the options you can use.

Examples
change_column(:suppliers, :name, :string, :limit => 80)
change_column(:accounts, :description, :text)


144
145
146
147
148
149
150
151
152
153
154
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 144

def change_column(table_name, column_name, type, options = {})
  type_sql = type_to_sql(type, *options.values_at(:limit, :precision, :scale))

  execute(squish_sql(<<-end_sql))
    ALTER TABLE #{quote_table_name(table_name)}
    ALTER COLUMN #{quote_column_name(column_name)} TYPE #{type_sql}
  end_sql

  change_column_null(table_name, column_name, !!options[:null]) if options.key?(:null)
  change_column_default(table_name, column_name, options[:default]) if options.key?(:default)
end

#change_column_default(table_name, column_name, default) ⇒ Object

Sets a new default value for a column. If you want to set the default value to NULL, you are out of luck. You need to DatabaseStatements#execute the appropriate SQL statement yourself.

Examples
change_column_default(:suppliers, :qualification, 'new')
change_column_default(:accounts, :authorized, 1)


162
163
164
165
166
167
168
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 162

def change_column_default(table_name, column_name, default)
  execute(squish_sql(<<-end_sql))
    ALTER TABLE #{quote_table_name(table_name)}
    ALTER #{quote_column_name(column_name)}
    SET DEFAULT #{quote(default)}
  end_sql
end

#change_column_null(table_name, column_name, null, default = nil) ⇒ Object



170
171
172
173
174
175
176
177
178
179
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 170

def change_column_null(table_name, column_name, null, default = nil)
  change_column_default(table_name, column_name, default) if default

  execute(squish_sql(<<-end_sql))
    UPDATE RDB$RELATION_FIELDS
    SET RDB$NULL_FLAG=#{quote(null ? nil : 1)}
    WHERE RDB$FIELD_NAME='#{ar_to_fb_case(column_name)}'
    AND RDB$RELATION_NAME='#{ar_to_fb_case(table_name)}'
  end_sql
end

#columns(table_name, _name = nil) ⇒ Object

Returns an array of Column objects for the table specified by table_name. See the concrete implementation for details on the expected parameter values.



53
54
55
56
57
58
59
60
61
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 53

def columns(table_name, _name = nil)
  column_definitions(table_name).map do |field|
    field.symbolize_keys!.each { |k, v| v.rstrip! if v.is_a?(String) }
    properties = field.values_at(:name, :default_source)
    properties += column_type_for(field)
    properties << !field[:null_flag]
    FbColumn.new(*properties, field.slice(:domain, :sub_type))
  end
end

#create_sequence(sequence_name) ⇒ Object

Creates a sequence

Examples
create_sequence('DOGS_SEQ')


100
101
102
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 100

def create_sequence(sequence_name)
  execute("CREATE SEQUENCE #{sequence_name}") rescue nil
end

#create_table(name, options = {}) ⇒ Object

:nodoc:



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 63

def create_table(name, options = {}) # :nodoc:
  if options.key? :temporary
    fail ActiveRecordError, 'Firebird does not support temporary tables'
  end

  if options.key? :as
    fail ActiveRecordError, 'Firebird does not support creating tables with a select'
  end

  needs_sequence = options[:id] != false
  while_ensuring_boolean_domain do
    super name, options do |table_def|
      yield table_def if block_given?
      needs_sequence ||= table_def.needs_sequence
    end
  end

  return if options[:sequence] == false || !needs_sequence
  create_sequence(options[:sequence] || default_sequence_name(name))
end

#drop_sequence(sequence_name) ⇒ Object

Drops a sequence

Examples
drop_sequence('DOGS_SEQ')


107
108
109
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 107

def drop_sequence(sequence_name)
  execute("DROP SEQUENCE #{sequence_name}") rescue nil
end

#drop_table(name, options = {}) ⇒ Object

:nodoc:



88
89
90
91
92
93
94
95
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 88

def drop_table(name, options = {}) # :nodoc:
  unless options[:sequence] == false
    sequence_name = options[:sequence] || default_sequence_name(name)
    drop_sequence(sequence_name) if sequence_exists?(sequence_name)
  end

  super
end

#index_name(table_name, options) ⇒ Object

:nodoc:



198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 198

def index_name(table_name, options) #:nodoc:
  if options.respond_to?(:keys) # legacy support
    if options[:column]
      "#{table_name}_#{Array.wrap(options[:column]) * '_'}"
    elsif options[:name]
      options[:name]
    else
      fail ArgumentError, "You must specify the index name"
    end
  else
    index_name(table_name, :column => options)
  end
end

#indexes(table_name, _name = nil) ⇒ Object

Returns an array of indexes for the given table.



30
31
32
33
34
35
36
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 30

def indexes(table_name, _name = nil)
  @connection.indexes.values.map { |ix|
    if ix.table_name == table_name.to_s && ix.index_name !~ /^rdb\$/
      IndexDefinition.new(table_name, ix.index_name, ix.unique, ix.columns)
    end
  }.compact
end

#native_database_typesObject

Returns a Hash of mappings from the abstract data types to the native database types. See TableDefinition#column for details on the recognized abstract data types.



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 8

def native_database_types
  {
    :primary_key => 'integer not null primary key',
    :string      => { :name => 'varchar', :limit => 255 },
    :text        => { :name => 'blob sub_type text' },
    :integer     => { :name => 'integer' },
    :float       => { :name => 'float' },
    :decimal     => { :name => 'decimal' },
    :datetime    => { :name => 'timestamp' },
    :timestamp   => { :name => 'timestamp' },
    :time        => { :name => 'time' },
    :date        => { :name => 'date' },
    :binary      => { :name => 'blob' },
    :boolean     => { :name => boolean_domain[:name] }
  }
end

#primary_key(table_name) ⇒ Object

:nodoc:



38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 38

def primary_key(table_name) #:nodoc:
  row = @connection.query(<<-end_sql)
    SELECT s.rdb$field_name
    FROM rdb$indices i
    JOIN rdb$index_segments s ON i.rdb$index_name = s.rdb$index_name
    LEFT JOIN rdb$relation_constraints c ON i.rdb$index_name = c.rdb$index_name
    WHERE i.rdb$relation_name = '#{ar_to_fb_case(table_name)}'
    AND c.rdb$constraint_type = 'PRIMARY KEY';
  end_sql

  row.first && fb_to_ar_case(row.first[0].rstrip)
end

#remove_column(table_name, column_name, type = nil, options = {}) ⇒ Object



129
130
131
132
133
134
135
136
137
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 129

def remove_column(table_name, column_name, type = nil, options = {})
  indexes(table_name).each do |i|
    if i.columns.any? { |c| c == column_name.to_s }
      remove_index! i.table, i.name
    end
  end

  super
end

#remove_index!(_table_name, index_name) ⇒ Object

:nodoc:



194
195
196
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 194

def remove_index!(_table_name, index_name) #:nodoc:
  execute "DROP INDEX #{quote_column_name(index_name)}"
end

#rename_column(table_name, column_name, new_column_name) ⇒ Object

Renames a column.

Example
rename_column(:suppliers, :description, :name)


184
185
186
187
188
189
190
191
192
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 184

def rename_column(table_name, column_name, new_column_name)
  execute(squish_sql(<<-end_sql))
    ALTER TABLE #{quote_table_name(table_name)}
    ALTER #{quote_column_name(column_name)}
    TO #{quote_column_name(new_column_name)}
  end_sql

  rename_column_indexes(table_name, column_name, new_column_name)
end

#rename_table(name, new_name) ⇒ Object



84
85
86
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 84

def rename_table(name, new_name)
  fail ActiveRecordError, 'Firebird does not support renaming tables.'
end

#tables(_name = nil) ⇒ Object



25
26
27
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 25

def tables(_name = nil)
  @connection.table_names
end

#type_to_sql(type, limit = nil, precision = nil, scale = nil) ⇒ Object



212
213
214
215
216
217
218
# File 'lib/active_record/connection_adapters/fb/schema_statements.rb', line 212

def type_to_sql(type, limit = nil, precision = nil, scale = nil)
  case type
  when :integer then integer_to_sql(limit)
  when :float   then float_to_sql(limit)
  else super
  end
end