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'}, :ean13 => {:name => 'ean13'} }

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



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

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



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

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

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

Raises:



237
238
239
240
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 237

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



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

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



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

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.



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

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

#extensionsObject



369
370
371
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 369

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.



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
366
367
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 319

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



313
314
315
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 313

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

#quote_with_extended_types(value, column = nil) ⇒ Object



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

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)


211
212
213
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 211

def supports_extensions?
  postgresql_version > 90100
end

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



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

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



295
296
297
# File 'lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb', line 295

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