Class: ActiveRecord::ConnectionAdapters::RedshiftAdapter

Inherits:
AbstractAdapter
  • Object
show all
Defined in:
lib/monkey_patch_redshift.rb

Overview

Patches extending the postgres adapter with new operations for managing sequences (and sets of sequence values), schemas and foreign keys. These should go into AbstractAdapter allowing any database adapter to take advantage of these SQL builders.

Instance Method Summary collapse

Instance Method Details

#add_foreign_key(referencing_table_name, referencing_field_name, referenced_table_name, referenced_field_name = :id) ⇒ optional

Add foreign key constraint to table.

Parameters:

  • referencing_table_name (String)

    the name of the table containing the foreign key

  • referencing_field_name (String)

    the name of foreign key column

  • referenced_table_name (String)

    the name of the table referenced by the foreign key

  • referenced_field_name (String) (defaults to: :id)

    (:id) the name of the column referenced by the foreign key

Returns:

  • (optional)

    undefined



111
112
113
# File 'lib/monkey_patch_redshift.rb', line 111

def add_foreign_key(referencing_table_name, referencing_field_name, referenced_table_name, referenced_field_name = :id)
  execute("ALTER TABLE #{referencing_table_name} add foreign key (#{referencing_field_name}) references #{referenced_table_name}(#{referenced_field_name})")
end

#create_schema(name, options = {}) ⇒ optional

Creates a schema given a name.

Parameters:

  • name (String)

    the name of the schema.

  • options (Hash) (defaults to: {})

    ({}) options for creating a schema

Options Hash (options):

  • :unless_exists (Boolean) — default: false

    check if schema exists.

Returns:

  • (optional)

    undefined



81
82
83
84
85
86
# File 'lib/monkey_patch_redshift.rb', line 81

def create_schema(name, options = {})
  if options[:unless_exists]
    return if execute("select count(*) from pg_namespace where nspname = '#{name}'").getvalue(0,0).to_i > 0
  end
  execute("CREATE SCHEMA #{name}")
end

#default_sequence_name(table_name, pk = nil) ⇒ Object

Returns the sequence name for a table’s primary key or some other specified key.

the default version strips off the schema name on the table (if it exists), as:

serial_sequence(table_name, pk || 'id').split('.').last

i can’t see any good reason for that – in fact, it seems completely broken – if you have a table public.foos and other.foos, you’ll fail to get the correct schema if you fetch the default schema name from model associated with other.foos



34
35
36
37
38
# File 'lib/monkey_patch_redshift.rb', line 34

def default_sequence_name(table_name, pk = nil) #:nodoc:
  serial_sequence(table_name, pk || 'id')
rescue ActiveRecord::StatementInvalid => e
  "#{table_name}_#{pk || 'id'}_seq"
end

#drop_schema(name, options = {}) ⇒ optional

Drop a schema given a name.

Parameters:

  • name (String)

    the name of the schema.

  • options (Hash) (defaults to: {})

    ({}) options for dropping a schema

Options Hash (options):

  • :if_exists (Boolean) — default: false

    check if schema exists.

  • :cascade (Boolean) — default: false

    drop dependant objects

Returns:

  • (optional)

    undefined



96
97
98
99
100
101
# File 'lib/monkey_patch_redshift.rb', line 96

def drop_schema(name, options = {})
  if options[:if_exists]
    return if execute("select count(*) from pg_namespace where nspname = '#{name}'").getvalue(0,0).to_i == 0
  end
  execute("DROP SCHEMA #{name}#{' cascade' if options[:cascade]}")
end

#next_sequence_value(sequence_name) ⇒ Integer

Get the next value in a sequence. Used on INSERT operation for partitioning like by_id because the ID is required before the insert so that the specific child table is known ahead of time.

Parameters:

  • sequence_name (String)

    the name of the sequence to fetch the next value from

Returns:

  • (Integer)

    the value from the sequence



47
48
49
# File 'lib/monkey_patch_redshift.rb', line 47

def next_sequence_value(sequence_name)
  return execute("select nextval('#{sequence_name}')").field_values("nextval").first.to_i
end

#next_sequence_values(sequence_name, batch_size) ⇒ Array<Integer>

Get the some next values in a sequence.

Parameters:

  • sequence_name (String)

    the name of the sequence to fetch the next values from

  • batch_size (Integer)

    count of values.

Returns:

  • (Array<Integer>)

    an array of values from the sequence



57
58
59
60
# File 'lib/monkey_patch_redshift.rb', line 57

def next_sequence_values(sequence_name, batch_size)
  result = execute("select nextval('#{sequence_name}') from generate_series(1, #{batch_size})")
  return result.field_values("nextval").map(&:to_i)
end

#partitioned_sql_adapter(model) ⇒ Object



20
21
22
# File 'lib/monkey_patch_redshift.rb', line 20

def partitioned_sql_adapter(model)
  return Partitioned::PartitionedBase::RedshiftSqlAdapter.new(model)
end

#prefetch_primary_key?(table_name) ⇒ Boolean

Causes active resource to fetch the primary key for the table (using next_sequence_value()) just before an insert. We need the prefetch to happen but we don’t have enough information here to determine if it should happen, so Relation::insert has been modified to request of the ActiveRecord::Base derived class if it requires a prefetch.

Parameters:

  • table_name (String)

    the table name to query

Returns:

  • (Boolean)

    returns true if the table should have its primary key prefetched.



70
71
72
# File 'lib/monkey_patch_redshift.rb', line 70

def prefetch_primary_key?(table_name)
  return false
end