Class: ODBCAdapter::Adapters::PostgreSQLODBCAdapter

Inherits:
ActiveRecord::ConnectionAdapters::ODBCAdapter show all
Defined in:
lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb

Overview

Overrides specific to PostgreSQL. Mostly taken from ActiveRecord::ConnectionAdapters::PostgreSQLAdapter

Constant Summary collapse

BOOLEAN_TYPE =
'bool'.freeze
PRIMARY_KEY =
'SERIAL PRIMARY KEY'.freeze

Constants inherited from ActiveRecord::ConnectionAdapters::ODBCAdapter

ActiveRecord::ConnectionAdapters::ODBCAdapter::ADAPTER_NAME, ActiveRecord::ConnectionAdapters::ODBCAdapter::ERR_DUPLICATE_KEY_VALUE

Constants included from DatabaseStatements

DatabaseStatements::SQL_NO_NULLS, DatabaseStatements::SQL_NULLABLE, DatabaseStatements::SQL_NULLABLE_UNKNOWN

Instance Attribute Summary

Attributes inherited from ActiveRecord::ConnectionAdapters::ODBCAdapter

#dbms

Instance Method Summary collapse

Methods inherited from ActiveRecord::ConnectionAdapters::ODBCAdapter

#active?, #adapter_name, #disconnect!, #initialize, #new_column, #reconnect!, #supports_migrations?

Methods included from SchemaStatements

#columns, #current_database, #index_name, #indexes, #primary_key, #tables, #views

Methods included from Quoting

#quote_column_name, #quoted_date

Methods included from DatabaseStatements

#begin_db_transaction, #commit_db_transaction, #exec_delete, #exec_query, #exec_rollback_db_transaction, #execute

Methods included from DatabaseLimits

#table_alias_length

Constructor Details

This class inherits a constructor from ActiveRecord::ConnectionAdapters::ODBCAdapter

Instance Method Details

#arel_visitorObject



14
15
16
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 14

def arel_visitor
  Arel::Visitors::PostgreSQL.new(self)
end

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



134
135
136
137
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 134

def change_column(table_name, column_name, type, options = {})
  execute("ALTER TABLE #{table_name} ALTER  #{column_name} TYPE #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}")
  change_column_default(table_name, column_name, options[:default]) if options_include_default?(options)
end

#change_column_default(table_name, column_name, default) ⇒ Object



139
140
141
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 139

def change_column_default(table_name, column_name, default)
  execute("ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DEFAULT #{quote(default)}")
end

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

Create a new PostgreSQL database. Options include :owner, :template, :encoding, :tablespace, and :connection_limit (note that MySQL uses :charset while PostgreSQL uses :encoding).

Example:

create_database config[:database], config
create_database 'foo_development', :encoding => 'unicode'


98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 98

def create_database(name, options = {})
  options = options.reverse_merge(encoding: 'utf8')

  option_string = options.symbolize_keys.sum do |key, value|
    case key
    when :owner
      " OWNER = \"#{value}\""
    when :template
      " TEMPLATE = \"#{value}\""
    when :encoding
      " ENCODING = '#{value}'"
    when :tablespace
      " TABLESPACE = \"#{value}\""
    when :connection_limit
      " CONNECTION LIMIT = #{value}"
    else
      ""
    end
  end

  execute("CREATE DATABASE #{quote_table_name(name)}#{option_string}")
end

#default_sequence_name(table_name, pk = nil) ⇒ Object

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



29
30
31
32
33
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 29

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

#disable_referential_integrityObject

:nodoc:



84
85
86
87
88
89
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 84

def disable_referential_integrity #:nodoc:
  execute(tables.map { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(';'))
  yield
ensure
  execute(tables.map { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER ALL" }.join(';'))
end

#distinct(columns, orders) ⇒ Object

Returns a SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.

PostgreSQL requires the ORDER BY columns in the select list for distinct queries, and requires that the ORDER BY include the distinct column.

distinct("posts.id", "posts.created_at desc")


161
162
163
164
165
166
167
168
169
170
171
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 161

def distinct(columns, orders)
  return "DISTINCT #{columns}" if orders.empty?

  # Construct a clean list of column names from the ORDER BY clause, removing
  # any ASC/DESC modifiers
  order_columns = orders.map { |s| s.gsub(/\s+(ASC|DESC)\s*(NULLS\s+(FIRST|LAST)\s*)?/i, '') }
  order_columns.reject! { |c| c.blank? }
  order_columns = order_columns.zip((0...order_columns.size).to_a).map { |s,i| "#{s} AS alias_#{i}" }

  "DISTINCT #{columns}, #{order_columns * ', '}"
end

#drop_database(name) ⇒ Object

Drops a PostgreSQL database.

Example:

drop_database 'matt_development'


125
126
127
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 125

def drop_database(name) #:nodoc:
  execute "DROP DATABASE IF EXISTS #{quote_table_name(name)}"
end

#insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) ⇒ Object

Executes an INSERT query and returns the new record’s ID



42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 42

def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
  unless pk
    table_ref = extract_table_ref_from_insert_sql(sql)
    pk = primary_key(table_ref) if table_ref
  end

  if pk
    select_value("#{sql} RETURNING #{quote_column_name(pk)}")
  else
    super
  end
end

#last_insert_id(sequence_name) ⇒ Object

Returns the current ID of a table’s sequence.



36
37
38
39
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 36

def last_insert_id(sequence_name)
  r = exec_query("SELECT currval('#{sequence_name}')", 'SQL')
  Integer(r.rows.first.first)
end

#native_database_typesObject

Override to handle booleans appropriately



10
11
12
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 10

def native_database_types
  @native_database_types ||= super.merge(boolean: { name: 'bool' })
end

#quote_string(string) ⇒ Object

Quotes a string, escaping any ‘ (single quote) and \ (backslash) characters.



80
81
82
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 80

def quote_string(string)
  string.gsub(/\\/, '\&\&').gsub(/'/, "''")
end

#remove_index!(_table_name, index_name) ⇒ Object



147
148
149
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 147

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

#rename_column(table_name, column_name, new_column_name) ⇒ Object



143
144
145
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 143

def rename_column(table_name, column_name, new_column_name)
  execute("ALTER TABLE #{table_name} RENAME #{column_name} TO #{new_column_name}")
end

#rename_index(table_name, old_name, new_name) ⇒ Object



151
152
153
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 151

def rename_index(table_name, old_name, new_name)
  execute("ALTER INDEX #{quote_column_name(old_name)} RENAME TO #{quote_table_name(new_name)}")
end

#rename_table(name, new_name) ⇒ Object

Renames a table.



130
131
132
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 130

def rename_table(name, new_name)
  execute("ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}")
end

#sql_for_insert(sql, pk, id_value, sequence_name, binds) ⇒ Object



56
57
58
59
60
61
62
63
64
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 56

def sql_for_insert(sql, pk, id_value, sequence_name, binds)
  unless pk
    table_ref = extract_table_ref_from_insert_sql(sql)
    pk = primary_key(table_ref) if table_ref
  end

  sql = "#{sql} RETURNING #{quote_column_name(pk)}" if pk
  [sql, binds]
end

#table_filter(schema_name, table_type) ⇒ Object

Filter for ODBCAdapter#tables Omits table from #tables if table_filter returns true



20
21
22
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 20

def table_filter(schema_name, table_type)
  %w[information_schema pg_catalog].include?(schema_name) || table_type !~ /TABLE/i
end

#truncate(table_name, name = nil) ⇒ Object



24
25
26
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 24

def truncate(table_name, name = nil)
  exec_query("TRUNCATE TABLE #{quote_table_name(table_name)}", name)
end

#type_cast(value, column) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
# File 'lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb', line 66

def type_cast(value, column)
  return super unless column

  case value
  when String
    return super unless 'bytea' == column.native_type
    { value: value, format: 1 }
  else
    super
  end
end