File: connection.rb

package info (click to toggle)
ruby-dataobjects 0.10.8-4
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 416 kB
  • sloc: ruby: 2,917; makefile: 4
file content (150 lines) | stat: -rw-r--r-- 4,301 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
begin
  require 'fastthread'
rescue LoadError
end

module DataObjects
  # An abstract connection to a DataObjects resource. The physical connection may be broken and re-established from time to time.
  class Connection

    include Logging

    # Make a connection to the database using the DataObjects::URI given.
    # Note that the physical connection may be delayed until the first command is issued, so success here doesn't necessarily mean you can connect.
    def self.new(uri_s)
      uri = DataObjects::URI::parse(uri_s)

      case uri.scheme.to_sym
      when :java
        warn 'JNDI URLs (connection strings) are only for use with JRuby' unless RUBY_PLATFORM =~ /java/

        driver   = uri.query.delete('scheme')
        driver   = uri.query.delete('driver')

        conn_uri = uri.to_s.gsub(/\?$/, '')
      when :jdbc
        warn 'JDBC URLs (connection strings) are only for use with JRuby' unless RUBY_PLATFORM =~ /java/

        path = uri.subscheme
        driver = if path.split(':').first == 'sqlite'
          'sqlite3'
        elsif path.split(':').first == 'postgresql'
          'postgres'
        else
          path.split(':').first
        end

        conn_uri = uri_s # NOTE: for now, do not reformat this JDBC connection
                         # string -- or, in other words, do not let
                         # DataObjects::URI#to_s be called -- as it is not
                         # correctly handling JDBC URLs, and in doing so, causing
                         # java.sql.DriverManager.getConnection to throw a
                         # 'No suitable driver found for...' exception.
      else
        driver   = uri.scheme
        conn_uri = uri
      end

      # Exceptions to how a driver class is determined for a given URI
      driver_class = if driver == 'sqlserver'
        'SqlServer'
      else
        driver.capitalize
      end

      clazz = DataObjects.const_get(driver_class)::Connection
      unless clazz.method_defined? :close
        if (uri.scheme.to_sym == :java)
          clazz.class_eval do
            alias close dispose
          end
        else
          clazz.class_eval do
            include Pooling
            alias close release
          end
        end
      end
      clazz.new(conn_uri)
    end

    # Ensure that all Connection subclasses handle pooling and logging uniformly.
    # See also DataObjects::Pooling and DataObjects::Logger
    def self.inherited(target)
      target.class_eval do

        # Allocate a Connection object from the pool, creating one if necessary. This method is active in Connection subclasses only.
        def self.new(*args)
          instance = allocate
          instance.send(:initialize, *args)
          instance
        end

        include Quoting
      end

      if driver_module_name = target.name.split('::')[-2]
        driver_module = DataObjects::const_get(driver_module_name)
        driver_module.class_eval <<-EOS, __FILE__, __LINE__
          def self.logger
            @logger
          end

          def self.logger=(logger)
            @logger = logger
          end
        EOS

        driver_module.logger = DataObjects::Logger.new(nil, :off)
      end
    end

    #####################################################
    # Standard API Definition
    #####################################################

    # Show the URI for this connection, without
    # the password the connection was setup with
    def to_s
      @uri.to_s
    end

    def initialize(uri) #:nodoc:
      raise NotImplementedError.new
    end

    def dispose #:nodoc:
      raise NotImplementedError.new
    end

    # Create a Command object of the right subclass using the given text
    def create_command(text)
      concrete_command.new(self, text)
    end

    def extension
      driver_namespace.const_get('Extension').new(self)
    end

    private

    def driver_namespace
      DataObjects::const_get(self.class.name.split('::')[-2])
    end

    def concrete_command
      @concrete_command || begin

        class << self
          private
          def concrete_command
            @concrete_command
          end
        end

        @concrete_command = DataObjects::const_get(self.class.name.split('::')[-2]).const_get('Command')
      end
    end

  end
end