Class: ActiveRecord::ConnectionAdapters::PostgreSQLAdapter

Inherits:
Object
  • Object
show all
Defined in:
lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb

Defined Under Namespace

Classes: ColumnDefinition, Table, TableDefinition, UnsupportedFeature

Constant Summary collapse

EXTENDED_TYPES =
{ :inet => {:name => 'inet'}, :cidr => {:name => 'cidr'}, :macaddr => {:name => 'macaddr'},
:uuid => {:name => 'uuid'}, :citext => {:name => 'citext'} }

Instance Method Summary collapse

Instance Method Details

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

The activerecord-jbdc-adapter implements PostgreSQLAdapter#add_column differently from the active-record version so we have to patch that version in JRuby, but not in MRI/YARV



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 253

def add_column(table_name, column_name, type, options = {})
  default = options[:default]
  notnull = options[:null] == false
  sql_type = type_to_sql(type, options[:limit], options[:precision], options[:scale])

  if options[:array]
    sql_type << '[]'
  end

  # Add the column.
  execute("ALTER TABLE #{quote_table_name(table_name)} ADD COLUMN #{quote_column_name(column_name)} #{sql_type}")

  change_column_default(table_name, column_name, default) if options_include_default?(options)
  change_column_null(table_name, column_name, false, default) if notnull
end

#add_column_options!(sql, options) ⇒ Object



213
214
215
216
217
218
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 213

def add_column_options!(sql, options)
  if options[:array] || options[:column].try(:array)
    sql << '[]'
  end
  super
end

#add_extension(extension_name, options = {}) ⇒ Object

Raises:



235
236
237
238
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 235

def add_extension(extension_name, options={})
  raise UnsupportedFeature.new('Extensions are not support by this version of PostgreSQL') unless supports_extensions?
  execute "CREATE extension IF NOT EXISTS \"#{extension_name}\""
end

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



220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 220

def add_index(table_name, column_name, options = {})
  index_name, unique, index_columns, _ = add_index_options(table_name, column_name, options)
  if options.is_a? Hash
    index_type = options[:using] ? " USING #{options[:using]} " : ""
    index_options = options[:where] ? " WHERE #{options[:where]}" : ""
    index_opclass = options[:index_opclass]
    index_algorithm = options[:algorithm] == :concurrently ? ' CONCURRENTLY' : ''

    if options[:algorithm].present? && options[:algorithm] != :concurrently
      raise ArgumentError.new 'Algorithm must be one of the following: :concurrently'
    end
  end
  execute "CREATE #{unique} INDEX#{index_algorithm} #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}#{index_type}(#{index_columns} #{index_opclass})#{index_options}"
end

#change_table(table_name, options = {}) ⇒ Object



240
241
242
243
244
245
246
247
248
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 240

def change_table(table_name, options = {})
  if supports_bulk_alter? && options[:bulk]
    recorder = ActiveRecord::Migration::CommandRecorder.new(self)
    yield Table.new(table_name, recorder)
    bulk_change_table(table_name, recorder.commands)
  else
    yield Table.new(table_name, self)
  end
end

#encoding_for_rubyObject

Translate from the current database encoding to the encoding we will force string array components into on retrievial.



200
201
202
203
204
205
206
207
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 200

def encoding_for_ruby
  @database_encoding ||= case ActiveRecord::Base.connection.encoding
                         when 'UTF8'
                           'UTF-8'
                         else
                           ActiveRecord::Base.connection.encoding
                         end
end

#extensionsObject



367
368
369
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 367

def extensions
  select_rows('select extname from pg_extension', 'extensions').map { |row| row[0] }.delete_if {|name| name == 'plpgsql'}
end

#indexes(table_name, name = nil) ⇒ Object

this is based upon rails 4 changes to include different index methods Returns an array of indexes for the given table.



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 317

def indexes(table_name, name = nil)
  opclasses
   result = select_rows(<<-SQL, name)
     SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid
     FROM pg_class t
     INNER JOIN pg_index d ON t.oid = d.indrelid
     INNER JOIN pg_class i ON d.indexrelid = i.oid
     WHERE i.relkind = 'i'
       AND d.indisprimary = 'f'
       AND t.relname = '#{table_name}'
       AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = ANY (current_schemas(false)) )
    ORDER BY i.relname
  SQL
  result.map do |row|
    index_name = row[0]
    unique = row[1] == 't'
    indkey = row[2].split(" ")
    inddef = row[3]
    oid = row[4]

    columns = Hash[select_rows(<<-SQL, "Columns for index #{row[0]} on #{table_name}")]
    SELECT a.attnum::text, a.attname
    FROM pg_attribute a
    WHERE a.attrelid = #{oid}
    AND a.attnum IN (#{indkey.join(",")})
    SQL
    column_names = columns.values_at(*indkey).compact

    # add info on sort order for columns (only desc order is explicitly specified, asc is the default)
    desc_order_columns = inddef.scan(/(\w+) DESC/).flatten
    orders = desc_order_columns.any? ? Hash[desc_order_columns.map {|order_column| [order_column, :desc]}] : {}
    #changed from rails 3.2
    where = inddef.scan(/WHERE (.+)$/).flatten[0]
    using = inddef.scan(/USING (.+?) /).flatten[0].to_sym
    if using
      index_op = inddef.scan(/USING .+? \(.+? (#{opclasses.join('|')})\)/).flatten
      index_op = index_op[0].to_sym if index_op.present?
    end
    if column_names.present?
      index_def = IndexDefinition.new(table_name, index_name, unique, column_names, [], orders)
      index_def.where = where
      index_def.using = using if using && using != :btree
      index_def.index_opclass = index_op if using && using != :btree && index_op
      index_def
    # else nil
    end
    #/changed
  end.compact
end

#opclassesObject



311
312
313
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 311

def opclasses
  @opclasses ||= select_rows('SELECT opcname FROM pg_opclass').flatten.uniq
end

#quote_with_extended_types(value, column = nil) ⇒ Object



298
299
300
301
302
303
304
305
306
307
308
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 298

def quote_with_extended_types(value, column = nil)
  if value.is_a? IPAddr
    "'#{type_cast(value, column)}'"
  elsif value.is_a? Array
    "'#{array_to_string(value, column, true)}'"
  elsif column.respond_to?(:array) && column.array && value =~ /^\{.*\}$/
    "'#{value}'"
  else
    quote_without_extended_types(value, column)
  end
end

#supports_extensions?Boolean

Returns:

  • (Boolean)


209
210
211
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 209

def supports_extensions?
  postgresql_version > 90100
end

#type_cast_extended(value, column, part_array = false) ⇒ Object



270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 270

def type_cast_extended(value, column, part_array = false)
  case value
  when NilClass
    if column.array && part_array
      'NULL'
    elsif column.array && !part_array
      value
    else
      type_cast_without_extended_types(value, column)
    end
  when Array
    if column.array
      array_to_string(value, column)
    else
      type_cast_without_extended_types(value, column)
    end
  when IPAddr
    ipaddr_to_string(value)
  else
    type_cast_without_extended_types(value, column)
  end
end

#type_cast_with_extended_types(value, column) ⇒ Object



293
294
295
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 293

def type_cast_with_extended_types(value, column)
  type_cast_extended(value, column)
end