Skip to content

Commit

Permalink
Pull out unnecessary methods and better comments
Browse files Browse the repository at this point in the history
  • Loading branch information
kddnewton committed Feb 3, 2017
1 parent 446429d commit cc2b47c
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 77 deletions.
63 changes: 18 additions & 45 deletions lib/odbc_adapter/adapters/mysql_odbc_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,6 @@ def truncate(table_name, name = nil)
execute("TRUNCATE TABLE #{quote_table_name(table_name)}", name)
end

def limited_update_conditions(where_sql, _quoted_table_name, _quoted_primary_key)
where_sql
end

def join_to_update(update, select) #:nodoc:
if select.limit || select.offset || select.orders.any?
subsubselect = select.clone
subsubselect.projections = [update.key]

subselect = Arel::SelectManager.new(select.engine)
subselect.project Arel.sql(update.key.name)
subselect.from subsubselect.as('__active_record_temp')

update.where update.key.in(subselect)
else
update.table select.source
update.wheres = select.constraints
end
end

# Quotes a string, escaping any ' (single quote) and \ (backslash)
# characters.
def quote_string(string)
Expand Down Expand Up @@ -113,9 +93,8 @@ def rename_table(name, new_name)
end

def change_column(table_name, column_name, type, options = {})
# column_name.to_s used in case column_name is a symbol
unless options_include_default?(options)
options[:default] = columns(table_name).find { |c| c.name == column_name.to_s }.default
options[:default] = column_for(table_name, column_name).default
end

change_column_sql = "ALTER TABLE #{table_name} CHANGE #{column_name} #{column_name} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
Expand All @@ -139,34 +118,15 @@ def change_column_null(table_name, column_name, null, default = nil)
end

def rename_column(table_name, column_name, new_column_name)
col = columns(table_name).detect { |c| c.name == column_name.to_s }
current_type = col.native_type
current_type << "(#{col.limit})" if col.limit
column = column_for(table_name, column_name)
current_type = column.native_type
current_type << "(#{column.limit})" if column.limit
execute("ALTER TABLE #{table_name} CHANGE #{column_name} #{new_column_name} #{current_type}")
end

# Skip primary key indexes
def indexes(table_name, name = nil)
super(table_name, name).delete_if { |i| i.unique && i.name =~ /^PRIMARY$/ }
end

# MySQL 5.x doesn't allow DEFAULT NULL for first timestamp column in a
# table
def options_include_default?(options)
if options.include?(:default) && options[:default].nil?
if options.include?(:column) && options[:column].native_type =~ /timestamp/i
options.delete(:default)
end
end
super(options)
end

def structure_dump
select_all("SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'").map do |table|
table.delete('Table_type')
sql = "SHOW CREATE TABLE #{quote_table_name(table.to_a.first.last)}"
exec_query(sql).first['Create Table'] + ";\n\n"
end.join
super(table_name, name).reject { |i| i.unique && i.name =~ /^PRIMARY$/ }
end

protected
Expand All @@ -179,6 +139,19 @@ def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
def last_inserted_id(_result)
select_value('SELECT LAST_INSERT_ID()').to_i
end

private

# MySQL 5.x doesn't allow DEFAULT NULL for first timestamp column in a
# table
def options_include_default?(options)
if options.include?(:default) && options[:default].nil?
if options.include?(:column) && options[:column].native_type =~ /timestamp/i
options.delete(:default)
end
end
super(options)
end
end
end
end
71 changes: 39 additions & 32 deletions lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ class PostgreSQLODBCAdapter < ActiveRecord::ConnectionAdapters::ODBCAdapter
BOOLEAN_TYPE = 'bool'.freeze
PRIMARY_KEY = 'SERIAL PRIMARY KEY'.freeze

alias :create :insert

# Override to handle booleans appropriately
def native_database_types
@native_database_types ||= super.merge(boolean: { name: 'bool' })
Expand All @@ -25,34 +27,14 @@ def truncate(table_name, name = nil)
exec_query("TRUNCATE TABLE #{quote_table_name(table_name)}", name)
end

# Returns the sequence name for a table's primary key or some other specified key.
# Returns the sequence name for a table's primary key or some other
# specified key.
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

# Returns the current ID of a table's sequence.
def last_insert_id(sequence_name)
r = exec_query("SELECT currval('#{sequence_name}')", 'SQL')
Integer(r.rows.first.first)
end

# Executes an INSERT query and returns the new record's ID
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
alias :create :insert

def sql_for_insert(sql, pk, id_value, sequence_name, binds)
unless pk
table_ref = extract_table_ref_from_insert_sql(sql)
Expand Down Expand Up @@ -88,13 +70,14 @@ def disable_referential_integrity #:nodoc:
execute(tables.map { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER ALL" }.join(';'))
end

# Create a new PostgreSQL database. Options include <tt>:owner</tt>, <tt>:template</tt>,
# <tt>:encoding</tt>, <tt>:tablespace</tt>, and <tt>:connection_limit</tt> (note that MySQL
# uses <tt>:charset</tt> while PostgreSQL uses <tt>:encoding</tt>).
# Create a new PostgreSQL database. Options include <tt>:owner</tt>,
# <tt>:template</tt>, <tt>:encoding</tt>, <tt>:tablespace</tt>, and
# <tt>:connection_limit</tt> (note that MySQL uses <tt>:charset</tt>
# while PostgreSQL uses <tt>:encoding</tt>).
#
# Example:
# create_database config[:database], config
# create_database 'foo_development', :encoding => 'unicode'
# create_database 'foo_development', encoding: 'unicode'
def create_database(name, options = {})
options = options.reverse_merge(encoding: 'utf8')

Expand All @@ -121,7 +104,7 @@ def create_database(name, options = {})
# Drops a PostgreSQL database.
#
# Example:
# drop_database 'matt_development'
# drop_database 'rails_development'
def drop_database(name) #:nodoc:
execute "DROP DATABASE IF EXISTS #{quote_table_name(name)}"
end
Expand Down Expand Up @@ -152,24 +135,48 @@ 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

# Returns a SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
# 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.
# 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")
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
# 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

protected

# Executes an INSERT query and returns the new record's ID
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

# Returns the current ID of a table's sequence.
def last_insert_id(sequence_name)
r = exec_query("SELECT currval('#{sequence_name}')", 'SQL')
Integer(r.rows.first.first)
end

private

def serial_sequence(table, column)
Expand Down

0 comments on commit cc2b47c

Please sign in to comment.