/lib/active_record/connection_adapters/oracle_enhanced_connection.rb

https://github.com/ctreatma/oracle-enhanced · Ruby · 119 lines · 93 code · 11 blank · 15 comment · 10 complexity · f01a1461fbc658af1c57d0d2c3b7633e MD5 · raw file

  1. module ActiveRecord
  2. module ConnectionAdapters
  3. # interface independent methods
  4. class OracleEnhancedConnection #:nodoc:
  5. def self.create(config)
  6. case ORACLE_ENHANCED_CONNECTION
  7. when :oci
  8. OracleEnhancedOCIConnection.new(config)
  9. when :jdbc
  10. OracleEnhancedJDBCConnection.new(config)
  11. else
  12. nil
  13. end
  14. end
  15. attr_reader :raw_connection
  16. # Oracle column names by default are case-insensitive, but treated as upcase;
  17. # for neatness, we'll downcase within Rails. EXCEPT that folks CAN quote
  18. # their column names when creating Oracle tables, which makes then case-sensitive.
  19. # I don't know anybody who does this, but we'll handle the theoretical case of a
  20. # camelCase column name. I imagine other dbs handle this different, since there's a
  21. # unit test that's currently failing test_oci.
  22. def oracle_downcase(column_name)
  23. return nil if column_name.nil?
  24. column_name =~ /[a-z]/ ? column_name : column_name.downcase
  25. end
  26. # Used always by JDBC connection as well by OCI connection when describing tables over database link
  27. def describe(name)
  28. name = name.to_s
  29. if name.include?('@')
  30. name, db_link = name.split('@')
  31. default_owner = select_value("SELECT username FROM all_db_links WHERE db_link = '#{db_link.upcase}'")
  32. db_link = "@#{db_link}"
  33. else
  34. db_link = nil
  35. default_owner = @owner
  36. end
  37. real_name = OracleEnhancedAdapter.valid_table_name?(name) ? name.upcase : name
  38. if real_name.include?('.')
  39. table_owner, table_name = real_name.split('.')
  40. else
  41. table_owner, table_name = default_owner, real_name
  42. end
  43. sql = <<-SQL
  44. SELECT owner, table_name, 'TABLE' name_type
  45. FROM all_tables#{db_link}
  46. WHERE owner = '#{table_owner}'
  47. AND table_name = '#{table_name}'
  48. UNION ALL
  49. SELECT owner, view_name table_name, 'VIEW' name_type
  50. FROM all_views#{db_link}
  51. WHERE owner = '#{table_owner}'
  52. AND view_name = '#{table_name}'
  53. UNION ALL
  54. SELECT table_owner, DECODE(db_link, NULL, table_name, table_name||'@'||db_link), 'SYNONYM' name_type
  55. FROM all_synonyms#{db_link}
  56. WHERE owner = '#{table_owner}'
  57. AND synonym_name = '#{table_name}'
  58. UNION ALL
  59. SELECT table_owner, DECODE(db_link, NULL, table_name, table_name||'@'||db_link), 'SYNONYM' name_type
  60. FROM all_synonyms#{db_link}
  61. WHERE owner = 'PUBLIC'
  62. AND synonym_name = '#{real_name}'
  63. SQL
  64. if result = select_one(sql)
  65. case result['name_type']
  66. when 'SYNONYM'
  67. describe("#{result['owner'] && "#{result['owner']}."}#{result['table_name']}#{db_link}")
  68. else
  69. db_link ? [result['owner'], result['table_name'], db_link] : [result['owner'], result['table_name']]
  70. end
  71. else
  72. raise OracleEnhancedConnectionException, %Q{"DESC #{name}" failed; does it exist?}
  73. end
  74. end
  75. # Returns a record hash with the column names as keys and column values
  76. # as values.
  77. def select_one(sql)
  78. result = select(sql)
  79. result.first if result
  80. end
  81. # Returns a single value from a record
  82. def select_value(sql)
  83. if result = select_one(sql)
  84. result.values.first
  85. end
  86. end
  87. # Returns an array of the values of the first column in a select:
  88. # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
  89. def select_values(sql, name = nil)
  90. result = select(sql, name = nil)
  91. result.map { |r| r.values.first }
  92. end
  93. end
  94. class OracleEnhancedConnectionException < StandardError #:nodoc:
  95. end
  96. end
  97. end
  98. # if MRI or YARV
  99. if !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby'
  100. ORACLE_ENHANCED_CONNECTION = :oci
  101. require 'active_record/connection_adapters/oracle_enhanced_oci_connection'
  102. # if JRuby
  103. elsif RUBY_ENGINE == 'jruby'
  104. ORACLE_ENHANCED_CONNECTION = :jdbc
  105. require 'active_record/connection_adapters/oracle_enhanced_jdbc_connection'
  106. else
  107. raise "Unsupported Ruby engine #{RUBY_ENGINE}"
  108. end