Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/cogent/rails_sql_views in…
Browse files Browse the repository at this point in the history
…to cogent
  • Loading branch information
lunks committed Apr 18, 2012
2 parents b33b0ee + 9d676d7 commit 252412e
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 8 deletions.
4 changes: 4 additions & 0 deletions Rakefile
Expand Up @@ -63,6 +63,10 @@ begin
"{bin,lib}/**/*"
]
s.add_dependency 'activerecord'
s.add_development_dependency 'flexmock'
s.add_development_dependency 'pg'
s.add_development_dependency 'mysql'
s.add_development_dependency 'mysql2'
end
rescue LoadError
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
Expand Down
6 changes: 5 additions & 1 deletion lib/ctreatma-rails_sql_views.rb
Expand Up @@ -33,10 +33,14 @@
require 'rails_sql_views/schema_dumper'
require 'rails_sql_views/loader'

$rails_sql_views_included = false

ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
include RailsSqlViews::ConnectionAdapters::SchemaStatements
def self.inherited(sub)
RailsSqlViews::Loader.load_extensions
unless $rails_sql_views_included && (Rails.env.test? || Rails.env.cucumber?)
RailsSqlViews::Loader.load_extensions
end
end
end

Expand Down
62 changes: 62 additions & 0 deletions lib/rails_sql_views/connection_adapters/mysql2_adapter.rb
@@ -0,0 +1,62 @@
module RailsSqlViews
module ConnectionAdapters
module Mysql2Adapter
def self.included(base)
if base.private_method_defined?(:supports_views?)
base.send(:public, :supports_views?)
end
end

# Returns true as this adapter supports views.
def supports_views?
true
end

def base_tables(name = nil) #:nodoc:
tables = []
execute("SHOW FULL TABLES WHERE TABLE_TYPE='BASE TABLE'").each{|row| tables << row[0]}
tables
end
alias nonview_tables base_tables

def views(name = nil) #:nodoc:
views = []
execute("SHOW FULL TABLES WHERE TABLE_TYPE='VIEW'").each{|row| views << row[0]}
views
end

def tables_with_views_included(name = nil)
nonview_tables(name) + views(name)
end

def structure_dump
structure = ""
base_tables.each do |table|
structure += select_one("SHOW CREATE TABLE #{quote_table_name(table)}")["Create Table"] + ";\n\n"
end

views.each do |view|
structure += select_one("SHOW CREATE VIEW #{quote_table_name(view)}")["Create View"] + ";\n\n"
end

return structure
end

# Get the view select statement for the specified table.
def view_select_statement(view, name=nil)
begin
row = execute("SHOW CREATE VIEW #{view}", name).each do |row|
return convert_statement(row[1]) if row[0] == view
end
rescue ActiveRecord::StatementInvalid => e
raise "No view called #{view} found"
end
end

private
def convert_statement(s)
s.gsub!(/.* AS (select .*)/, '\1')
end
end
end
end
14 changes: 9 additions & 5 deletions lib/rails_sql_views/connection_adapters/mysql_adapter.rb
@@ -1,9 +1,13 @@
module RailsSqlViews
module ConnectionAdapters
module MysqlAdapter
REQUIRED_METHODS = [:supports_views?]

def self.included(base)
if base.private_method_defined?(:supports_views?)
base.send(:public, :supports_views?)
base.class_eval do
def self.method_added(method)
public(method) if REQUIRED_METHODS.include?(method) && !self.public_method_defined?(method)
end
end
end

Expand All @@ -18,7 +22,7 @@ def base_tables(name = nil) #:nodoc:
tables
end
alias nonview_tables base_tables

def views(name = nil) #:nodoc:
views = []
execute("SHOW FULL TABLES WHERE TABLE_TYPE='VIEW'").each{|row| views << row[0]}
Expand All @@ -28,7 +32,7 @@ def views(name = nil) #:nodoc:
def tables_with_views_included(name = nil)
nonview_tables(name) + views(name)
end

def structure_dump
structure = ""
base_tables.each do |table|
Expand All @@ -52,7 +56,7 @@ def view_select_statement(view, name=nil)
raise "No view called #{view} found"
end
end

private
def convert_statement(s)
s.gsub!(/.* AS (select .*)/, '\1')
Expand Down
Expand Up @@ -2,7 +2,7 @@ module RailsSqlViews
module ConnectionAdapters
module PostgreSQLAdapter
def self.included(base)
base.alias_method_chain :tables, :views_included
base.alias_method_chain :tables, :views_included unless method_defined?(:tables_with_views_included)
end
# Returns true as this adapter supports views.
def supports_views?
Expand Down
4 changes: 3 additions & 1 deletion lib/rails_sql_views/loader.rb
@@ -1,7 +1,7 @@

module RailsSqlViews
module Loader
SUPPORTED_ADAPTERS = %w( Mysql PostgreSQL SQLServer SQLite OracleEnhanced )
SUPPORTED_ADAPTERS = %w( Mysql Mysql2 PostgreSQL SQLServer SQLite OracleEnhanced )

def self.load_extensions
SUPPORTED_ADAPTERS.each do |db|
Expand All @@ -10,6 +10,8 @@ def self.load_extensions
ActiveRecord::ConnectionAdapters.const_get("#{db}Adapter").class_eval do
include RailsSqlViews::ConnectionAdapters::AbstractAdapter
include RailsSqlViews::ConnectionAdapters.const_get("#{db}Adapter")
# prevent reloading extension when the environment is reloaded
$rails_sql_views_included = true
end
end
end
Expand Down
32 changes: 32 additions & 0 deletions test/connection/native_mysql2/connection.rb
@@ -0,0 +1,32 @@
print "Using native MySQL2\n"

adapter_name = 'mysql2'
config = YAML.load_file(File.join(File.dirname(__FILE__), '/../../connection.yml'))[adapter_name]

#require 'logger'
#ActiveRecord::Base.logger = Logger.new("debug.log")

ActiveRecord::Base.silence do
ActiveRecord::Base.configurations = {
config['database'] => {
:adapter => adapter_name,
:username => config['username'],
:password => config['password'],
:host => config['host'],
:database => config['database'],
:encoding => config['encoding'],
:schema_file => config['schema_file'],
}
}

ActiveRecord::Base.establish_connection config['database']
ActiveRecord::Migration.verbose = false

puts "Resetting database"
conn = ActiveRecord::Base.connection
conn.recreate_database(conn.current_database)
conn.reconnect!
lines = open(File.join(File.dirname(__FILE__), ActiveRecord::Base.configurations[config['database']][:schema_file])).readlines
lines.join.split(';').each { |line| conn.execute(line) }
conn.reconnect!
end
33 changes: 33 additions & 0 deletions test/connection/native_mysql2/schema.sql
@@ -0,0 +1,33 @@
drop table if exists people;
create table people (
id int(11) DEFAULT NULL auto_increment PRIMARY KEY,
first_name char(255),
last_name char(255),
ssn char(64),
address_id integer
);
drop table if exists people2;
create table people2 (
id int(11) DEFAULT NULL auto_increment PRIMARY KEY,
first_name char(255),
last_name char(255),
ssn char(64)
);
drop table if exists places;
create table places (
id int(11) DEFAULT NULL auto_increment PRIMARY KEY,
address text,
city char(255),
cstate char(255),
country char(2)
);
drop table if exists items;
create table items (
id int(11) DEFAULT NULL auto_increment PRIMARY KEY,
person_id int(11)
);
drop table if exists items_people;
create table items_people (
person_id int(11),
item_id int(11)
);
6 changes: 6 additions & 0 deletions test/schema.native_mysql.expected.rb
Expand Up @@ -48,4 +48,10 @@
v.column :address_id
end

create_view "v_profile", "select `people`.`first_name` AS `first_name`,`people`.`last_name` AS `last_name`,`people`.`ssn` AS `ssn` from `people` union select `people2`.`first_name` AS `first_name`,`people2`.`last_name` AS `last_name`,`people2`.`ssn` AS `ssn` from `people2`", :force => true do |v|
v.column :first_name
v.column :last_name
v.column :ssn
end

end
57 changes: 57 additions & 0 deletions test/schema.native_mysql2.expected.rb
@@ -0,0 +1,57 @@
# This file is auto-generated from the current state of the database. Instead of editing this file,
# please use the migrations feature of Active Record to incrementally modify your database, and
# then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your database schema. If you need
# to create the application database on another system, you should be using db:schema:load, not running
# all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended to check this file into your version control system.

ActiveRecord::Schema.define(:version => 0) do

create_table "items", :force => true do |t|
t.integer "person_id"
end

create_table "items_people", :id => false, :force => true do |t|
t.integer "person_id"
t.integer "item_id"
end

create_table "people", :force => true do |t|
t.string "first_name"
t.string "last_name"
t.string "ssn", :limit => 64
t.integer "address_id"
end

create_table "people2", :force => true do |t|
t.string "first_name"
t.string "last_name"
t.string "ssn", :limit => 64
end

create_table "places", :force => true do |t|
t.text "address"
t.string "city"
t.string "cstate"
t.string "country", :limit => 2
end

create_view "v_people", "select `people`.`id` AS `id`,`people`.`first_name` AS `f_name`,`people`.`last_name` AS `l_name`,`people`.`ssn` AS `social_security`,`people`.`address_id` AS `address_id` from `people`", :force => true do |v|
v.column :id
v.column :f_name
v.column :l_name
v.column :social_security
v.column :address_id
end

create_view "v_profile", "select `people`.`first_name` AS `first_name`,`people`.`last_name` AS `last_name`,`people`.`ssn` AS `ssn` from `people` union select `people2`.`first_name` AS `first_name`,`people2`.`last_name` AS `last_name`,`people2`.`ssn` AS `ssn` from `people2`", :force => true do |v|
v.column :first_name
v.column :last_name
v.column :ssn
end

end

0 comments on commit 252412e

Please sign in to comment.