Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,8 @@ def self.create(config)
def describe(name)
name = name.to_s
if name.include?("@")
name, db_link = name.split("@")
default_owner = _select_value("SELECT username FROM all_db_links WHERE db_link = '#{db_link.upcase}'")
db_link = "@#{db_link}"
raise ArgumentError "db link is not supported"
else
db_link = nil
default_owner = @owner
end
real_name = OracleEnhanced::Quoting.valid_table_name?(name) ? name.upcase : name
Expand All @@ -39,31 +36,31 @@ def describe(name)
end
sql = <<-SQL.strip.gsub(/\s+/, " ")
SELECT owner, table_name, 'TABLE' name_type
FROM all_tables#{db_link}
FROM all_tables
WHERE owner = '#{table_owner}'
AND table_name = '#{table_name}'
UNION ALL
SELECT owner, view_name table_name, 'VIEW' name_type
FROM all_views#{db_link}
FROM all_views
WHERE owner = '#{table_owner}'
AND view_name = '#{table_name}'
UNION ALL
SELECT table_owner, DECODE(db_link, NULL, table_name, table_name||'@'||db_link), 'SYNONYM' name_type
FROM all_synonyms#{db_link}
SELECT table_owner, table_name, 'SYNONYM' name_type
FROM all_synonyms
WHERE owner = '#{table_owner}'
AND synonym_name = '#{table_name}'
UNION ALL
SELECT table_owner, DECODE(db_link, NULL, table_name, table_name||'@'||db_link), 'SYNONYM' name_type
FROM all_synonyms#{db_link}
SELECT table_owner, table_name, 'SYNONYM' name_type
FROM all_synonyms
WHERE owner = 'PUBLIC'
AND synonym_name = '#{real_name}'
SQL
if result = _select_one(sql)
case result["name_type"]
when "SYNONYM"
describe("#{result['owner'] && "#{result['owner']}."}#{result['table_name']}#{db_link}")
describe("#{result['owner'] && "#{result['owner']}."}#{result['table_name']}")
else
db_link ? [result["owner"], result["table_name"], db_link] : [result["owner"], result["table_name"]]
[result["owner"], result["table_name"]]
end
else
raise OracleEnhanced::ConnectionException, %Q{"DESC #{name}" failed; does it exist?}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def initialize(
end
end

class SynonymDefinition < Struct.new(:name, :table_owner, :table_name, :db_link) #:nodoc:
class SynonymDefinition < Struct.new(:name, :table_owner, :table_name) #:nodoc:
end

class IndexDefinition < ActiveRecord::ConnectionAdapters::IndexDefinition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ def synonyms(stream)
next if ignored? syn.name
table_name = syn.table_name
table_name = "#{syn.table_owner}.#{table_name}" if syn.table_owner
table_name = "#{table_name}@#{syn.db_link}" if syn.db_link
stream.print " add_synonym #{syn.name.inspect}, #{table_name.inspect}, force: true"
stream.puts
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def table_exists?(table_name)
end

def data_source_exists?(table_name)
(_owner, table_name, _db_link) = @connection.describe(table_name)
(_owner, table_name) = @connection.describe(table_name)
true
rescue
false
Expand All @@ -69,18 +69,18 @@ def materialized_views #:nodoc:
# get synonyms for schema dump
def synonyms
result = select_all(<<-SQL.strip.gsub(/\s+/, " "), "synonyms")
SELECT synonym_name, table_owner, table_name, db_link
SELECT synonym_name, table_owner, table_name
FROM all_synonyms where owner = SYS_CONTEXT('userenv', 'session_user')
SQL

result.collect do |row|
OracleEnhanced::SynonymDefinition.new(oracle_downcase(row["synonym_name"]),
oracle_downcase(row["table_owner"]), oracle_downcase(row["table_name"]), oracle_downcase(row["db_link"]))
oracle_downcase(row["table_owner"]), oracle_downcase(row["table_name"]))
end
end

def indexes(table_name) #:nodoc:
(owner, table_name, db_link) = @connection.describe(table_name)
(owner, table_name) = @connection.describe(table_name)
default_tablespace_name = default_tablespace

result = select_all(<<-SQL.strip.gsub(/\s+/, " "), "indexes", [bind_string("owner", owner), bind_string("owner", owner)])
Expand All @@ -89,11 +89,11 @@ def indexes(table_name) #:nodoc:
LOWER(i.tablespace_name) AS tablespace_name,
LOWER(c.column_name) AS column_name, e.column_expression,
atc.virtual_column
FROM all_indexes#{db_link} i
JOIN all_ind_columns#{db_link} c ON c.index_name = i.index_name AND c.index_owner = i.owner
LEFT OUTER JOIN all_ind_expressions#{db_link} e ON e.index_name = i.index_name AND
FROM all_indexes i
JOIN all_ind_columns c ON c.index_name = i.index_name AND c.index_owner = i.owner
LEFT OUTER JOIN all_ind_expressions e ON e.index_name = i.index_name AND
e.index_owner = i.owner AND e.column_position = c.column_position
LEFT OUTER JOIN all_tab_cols#{db_link} atc ON i.table_name = atc.table_name AND
LEFT OUTER JOIN all_tab_cols atc ON i.table_name = atc.table_name AND
c.column_name = atc.column_name AND i.owner = atc.owner AND atc.hidden_column = 'NO'
WHERE i.owner = :owner
AND i.table_owner = :owner
Expand All @@ -114,7 +114,7 @@ def indexes(table_name) #:nodoc:
procedure_name = default_datastore_procedure(row["index_name"])
source = select_values(<<-SQL.strip.gsub(/\s+/, " "), "procedure", [bind_string("owner", owner), bind_string("procedure_name", procedure_name.upcase)]).join
SELECT text
FROM all_source#{db_link}
FROM all_source
WHERE owner = :owner
AND name = :procedure_name
ORDER BY line
Expand Down Expand Up @@ -343,9 +343,9 @@ def index_name(table_name, options) #:nodoc:
#
# Will always query database and not index cache.
def index_name_exists?(table_name, index_name)
(owner, table_name, db_link) = @connection.describe(table_name)
(owner, table_name) = @connection.describe(table_name)
result = select_value(<<-SQL.strip.gsub(/\s+/, " "), "index name exists")
SELECT 1 FROM all_indexes#{db_link} i
SELECT 1 FROM all_indexes i
WHERE i.owner = '#{owner}'
AND i.table_owner = '#{owner}'
AND i.table_name = '#{table_name}'
Expand Down Expand Up @@ -465,9 +465,9 @@ def change_column_comment(table_name, column_name, comment) #:nodoc:
end

def table_comment(table_name) #:nodoc:
(owner, table_name, db_link) = @connection.describe(table_name)
(owner, table_name) = @connection.describe(table_name)
select_value(<<-SQL.strip.gsub(/\s+/, " "), "Table comment", [bind_string("owner", owner), bind_string("table_name", table_name)])
SELECT comments FROM all_tab_comments#{db_link}
SELECT comments FROM all_tab_comments
WHERE owner = :owner
AND table_name = :table_name
SQL
Expand All @@ -481,9 +481,9 @@ def table_options(table_name) # :nodoc:

def column_comment(table_name, column_name) #:nodoc:
# TODO: it does not exist in Abstract adapter
(owner, table_name, db_link) = @connection.describe(table_name)
(owner, table_name) = @connection.describe(table_name)
select_value(<<-SQL.strip.gsub(/\s+/, " "), "Column comment", [bind_string("owner", owner), bind_string("table_name", table_name), bind_string("column_name", column_name.upcase)])
SELECT comments FROM all_col_comments#{db_link}
SELECT comments FROM all_col_comments
WHERE owner = :owner
AND table_name = :table_name
AND column_name = :column_name
Expand All @@ -509,16 +509,16 @@ def tablespace(table_name)

# get table foreign keys for schema dump
def foreign_keys(table_name) #:nodoc:
(owner, desc_table_name, db_link) = @connection.describe(table_name)
(owner, desc_table_name) = @connection.describe(table_name)

fk_info = select_all(<<-SQL.strip.gsub(/\s+/, " "), "Foreign Keys", [bind_string("owner", owner), bind_string("desc_table_name", desc_table_name)])
SELECT r.table_name to_table
,rc.column_name references_column
,cc.column_name
,c.constraint_name name
,c.delete_rule
FROM all_constraints#{db_link} c, all_cons_columns#{db_link} cc,
all_constraints#{db_link} r, all_cons_columns#{db_link} rc
FROM all_constraints c, all_cons_columns cc,
all_constraints r, all_cons_columns rc
WHERE c.owner = :owner
AND c.table_name = :desc_table_name
AND c.constraint_type = 'R'
Expand Down
30 changes: 15 additions & 15 deletions lib/active_record/connection_adapters/oracle_enhanced_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -427,8 +427,8 @@ def next_sequence_value(sequence_name)
def prefetch_primary_key?(table_name = nil)
return true if table_name.nil?
table_name = table_name.to_s
owner, desc_table_name, db_link = @connection.describe(table_name)
do_not_prefetch = !has_primary_key?(table_name, owner, desc_table_name, db_link) || has_primary_key_trigger?(table_name, owner, desc_table_name, db_link)
owner, desc_table_name = @connection.describe(table_name)
do_not_prefetch = !has_primary_key?(table_name, owner, desc_table_name) || has_primary_key_trigger?(table_name, owner, desc_table_name)
!do_not_prefetch
end

Expand Down Expand Up @@ -495,14 +495,14 @@ def default_tablespace
end

# check if table has primary key trigger with _pkt suffix
def has_primary_key_trigger?(table_name, owner = nil, desc_table_name = nil, db_link = nil)
(owner, desc_table_name, db_link) = @connection.describe(table_name) unless owner
def has_primary_key_trigger?(table_name, owner = nil, desc_table_name = nil)
(owner, desc_table_name) = @connection.describe(table_name) unless owner

trigger_name = default_trigger_name(table_name).upcase

!!select_value(<<-SQL.strip.gsub(/\s+/, " "), "Primary Key Trigger", [bind_string("owner", owner), bind_string("trigger_name", trigger_name), bind_string("owner", owner), bind_string("table_name", desc_table_name)])
SELECT trigger_name
FROM all_triggers#{db_link}
FROM all_triggers
WHERE owner = :owner
AND trigger_name = :trigger_name
AND table_owner = :owner
Expand All @@ -512,7 +512,7 @@ def has_primary_key_trigger?(table_name, owner = nil, desc_table_name = nil, db_
end

def column_definitions(table_name)
(owner, desc_table_name, db_link) = @connection.describe(table_name)
(owner, desc_table_name) = @connection.describe(table_name)

select_all(<<-SQL.strip.gsub(/\s+/, " "), "Column definitions", [bind_string("owner", owner), bind_string("table_name", desc_table_name)])
SELECT cols.column_name AS name, cols.data_type AS sql_type,
Expand All @@ -526,7 +526,7 @@ def column_definitions(table_name)
NULL) AS limit,
DECODE(data_type, 'NUMBER', data_scale, NULL) AS scale,
comments.comments as column_comment
FROM all_tab_cols#{db_link} cols, all_col_comments#{db_link} comments
FROM all_tab_cols cols, all_col_comments comments
WHERE cols.owner = :owner
AND cols.table_name = :table_name
AND cols.hidden_column = 'NO'
Expand All @@ -539,20 +539,20 @@ def column_definitions(table_name)

# Find a table's primary key and sequence.
# *Note*: Only primary key is implemented - sequence will be nil.
def pk_and_sequence_for(table_name, owner = nil, desc_table_name = nil, db_link = nil) #:nodoc:
(owner, desc_table_name, db_link) = @connection.describe(table_name) unless owner
def pk_and_sequence_for(table_name, owner = nil, desc_table_name = nil) #:nodoc:
(owner, desc_table_name) = @connection.describe(table_name) unless owner

seqs = select_values(<<-SQL.strip.gsub(/\s+/, " "), "Sequence", [bind_string("owner", owner), bind_string("sequence_name", default_sequence_name(desc_table_name).upcase)])
select us.sequence_name
from all_sequences#{db_link} us
from all_sequences us
where us.sequence_owner = :owner
and us.sequence_name = :sequence_name
SQL

# changed back from user_constraints to all_constraints for consistency
pks = select_values(<<-SQL.strip.gsub(/\s+/, " "), "Primary Key", [bind_string("owner", owner), bind_string("table_name", desc_table_name)])
SELECT cc.column_name
FROM all_constraints#{db_link} c, all_cons_columns#{db_link} cc
FROM all_constraints c, all_cons_columns cc
WHERE c.owner = :owner
AND c.table_name = :table_name
AND c.constraint_type = 'P'
Expand All @@ -577,16 +577,16 @@ def primary_key(table_name)
pk_and_sequence && pk_and_sequence.first
end

def has_primary_key?(table_name, owner = nil, desc_table_name = nil, db_link = nil) #:nodoc:
!pk_and_sequence_for(table_name, owner, desc_table_name, db_link).nil?
def has_primary_key?(table_name, owner = nil, desc_table_name = nil) #:nodoc:
!pk_and_sequence_for(table_name, owner, desc_table_name).nil?
end

def primary_keys(table_name) # :nodoc:
(owner, desc_table_name, db_link) = @connection.describe(table_name) unless owner
(owner, desc_table_name) = @connection.describe(table_name) unless owner

pks = select_values(<<-SQL.strip.gsub(/\s+/, " "), "Primary Keys", [bind_string("owner", owner), bind_string("table_name", desc_table_name)])
SELECT cc.column_name
FROM all_constraints#{db_link} c, all_cons_columns#{db_link} cc
FROM all_constraints c, all_cons_columns cc
WHERE c.owner = :owner
AND c.table_name = :table_name
AND c.constraint_type = 'P'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,13 +252,6 @@ def drop_test_posts_table
expect(standard_dump).to match(/add_synonym "test_synonym", "schema_name.table_name", force: true/)
end

it "should include synonym to other database table in schema dump" do
schema_define do
add_synonym :test_synonym, "table_name@link_name", force: true
end
expect(standard_dump).to match(/add_synonym "test_synonym", "table_name@link_name(\.[-A-Za-z0-9_]+)*", force: true/)
end

it "should not include ignored table names in schema dump" do
schema_define do
add_synonym :test_synonym, "schema_name.table_name", force: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1028,18 +1028,6 @@ class ::TestPost < ActiveRecord::Base
TestPost.create(title: "test")
end.not_to raise_error
end

it "should create synonym to table over database link" do
db_link = @db_link
schema_define do
add_synonym :synonym_to_posts, "test_posts@#{db_link}", force: true
add_synonym :synonym_to_posts_seq, "test_posts_seq@#{db_link}", force: true
end
expect do
TestPost.create(title: "test")
end.not_to raise_error
end

end

describe "alter columns with column cache" do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,55 +99,6 @@ class ::TestEmployee2 < ActiveRecord::Base
end
end

describe "access table over database link" do
before(:all) do
@conn = ActiveRecord::Base.connection
@db_link = "db_link"
@sys_conn = ActiveRecord::Base.oracle_enhanced_connection(SYSTEM_CONNECTION_PARAMS)
@sys_conn.drop_table :test_posts, if_exists: true
@sys_conn.create_table :test_posts do |t|
t.string :title
# cannot update LOBs over database link
t.string :body
t.timestamps null: true
end
@db_link_username = SYSTEM_CONNECTION_PARAMS[:username]
@db_link_password = SYSTEM_CONNECTION_PARAMS[:password]
@db_link_database = SYSTEM_CONNECTION_PARAMS[:database]
@conn.execute "DROP DATABASE LINK #{@db_link}" rescue nil
@conn.execute "CREATE DATABASE LINK #{@db_link} CONNECT TO #{@db_link_username} IDENTIFIED BY \"#{@db_link_password}\" USING '#{@db_link_database}'"
@conn.execute "CREATE OR REPLACE SYNONYM test_posts FOR test_posts@#{@db_link}"
@conn.execute "CREATE OR REPLACE SYNONYM test_posts_seq FOR test_posts_seq@#{@db_link}"
class ::TestPost < ActiveRecord::Base
end
TestPost.table_name = "test_posts"
end

after(:all) do
@conn.execute "DROP SYNONYM test_posts"
@conn.execute "DROP SYNONYM test_posts_seq"
@conn.execute "DROP DATABASE LINK #{@db_link}" rescue nil
@sys_conn.drop_table :test_posts, if_exists: true
Object.send(:remove_const, "TestPost") rescue nil
ActiveRecord::Base.clear_cache!
end

it "should verify database link" do
@conn.select_value("select * from dual@#{@db_link}") == "X"
end

it "should get column names" do
expect(TestPost.column_names).to eq(["id", "title", "body", "created_at", "updated_at"])
end

it "should create record" do
p = TestPost.create(title: "Title", body: "Body")
expect(p.id).not_to be_nil
expect(TestPost.find(p.id)).not_to be_nil
end

end

describe "session information" do
before(:all) do
@conn = ActiveRecord::Base.connection
Expand Down