2 module ConnectionAdapters
3 # interface independent methods
4 class OracleEnhancedConnection #:nodoc:
6 def self.create(config)
7 case ORACLE_ENHANCED_CONNECTION
9 OracleEnhancedOCIConnection.new(config)
11 OracleEnhancedJDBCConnection.new(config)
17 attr_reader :raw_connection
19 # Oracle column names by default are case-insensitive, but treated as upcase;
20 # for neatness, we'll downcase within Rails. EXCEPT that folks CAN quote
21 # their column names when creating Oracle tables, which makes then case-sensitive.
22 # I don't know anybody who does this, but we'll handle the theoretical case of a
23 # camelCase column name. I imagine other dbs handle this different, since there's a
24 # unit test that's currently failing test_oci.
25 def oracle_downcase(column_name)
26 return nil if column_name.nil?
27 column_name =~ /[a-z]/ ? column_name : column_name.downcase
30 # Used always by JDBC connection as well by OCI connection when describing tables over database link
34 name, db_link = name.split('@')
35 default_owner = select_value("SELECT username FROM all_db_links WHERE db_link = '#{db_link.upcase}'")
36 db_link = "@#{db_link}"
39 default_owner = @owner
41 real_name = OracleEnhancedAdapter.valid_table_name?(name) ? name.upcase : name
42 if real_name.include?('.')
43 table_owner, table_name = real_name.split('.')
45 table_owner, table_name = default_owner, real_name
48 SELECT owner, table_name, 'TABLE' name_type
49 FROM all_tables#{db_link}
50 WHERE owner = '#{table_owner}'
51 AND table_name = '#{table_name}'
53 SELECT owner, view_name table_name, 'VIEW' name_type
54 FROM all_views#{db_link}
55 WHERE owner = '#{table_owner}'
56 AND view_name = '#{table_name}'
58 SELECT table_owner, DECODE(db_link, NULL, table_name, table_name||'@'||db_link), 'SYNONYM' name_type
59 FROM all_synonyms#{db_link}
60 WHERE owner = '#{table_owner}'
61 AND synonym_name = '#{table_name}'
63 SELECT table_owner, DECODE(db_link, NULL, table_name, table_name||'@'||db_link), 'SYNONYM' name_type
64 FROM all_synonyms#{db_link}
65 WHERE owner = 'PUBLIC'
66 AND synonym_name = '#{real_name}'
68 if result = select_one(sql)
69 case result['name_type']
71 describe("#{result['owner'] && "#{result['owner']}."}#{result['table_name']}#{db_link}")
73 db_link ? [result['owner'], result['table_name'], db_link] : [result['owner'], result['table_name']]
76 raise OracleEnhancedConnectionException, %Q{"DESC #{name}" failed; does it exist?}
80 # Returns a record hash with the column names as keys and column values
84 result.first if result
87 # Returns a single value from a record
89 if result = select_one(sql)
94 # Returns an array of the values of the first column in a select:
95 # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
96 def select_values(sql)
98 result.map { |r| r.values.first }
103 class OracleEnhancedConnectionException < StandardError #:nodoc:
110 if !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby'
111 ORACLE_ENHANCED_CONNECTION = :oci
112 require 'active_record/connection_adapters/oracle_enhanced_oci_connection'
114 elsif RUBY_ENGINE == 'jruby'
115 ORACLE_ENHANCED_CONNECTION = :jdbc
116 require 'active_record/connection_adapters/oracle_enhanced_jdbc_connection'
118 raise "Unsupported Ruby engine #{RUBY_ENGINE}"