aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/connection_adapters/db2_adapter.rb
blob: 225ade04416973f56a61ef549785c20aad7f094e (plain) (blame)
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
# Author: Maik Schmidt <contact@maik-schmidt.de>

require 'active_record/connection_adapters/abstract_adapter'

begin
  require 'db2/db2cli' unless self.class.const_defined?(:DB2CLI)
  require 'active_record/vendor/db2'

  module ActiveRecord
    class Base
      # Establishes a connection to the database that's used by
      # all Active Record objects
      def self.db2_connection(config) # :nodoc:
        symbolize_strings_in_hash(config)
        usr = config[:username]
        pwd = config[:password]

        if config.has_key?(:database)
          database = config[:database]
        else
          raise ArgumentError, "No database specified. Missing argument: database."
        end

        connection = DB2::Connection.new(DB2::Environment.new)
        connection.connect(database, usr, pwd)
        ConnectionAdapters::DB2Adapter.new(connection)
      end
    end

    module ConnectionAdapters
      class DB2Adapter < AbstractAdapter # :nodoc:
        def select_all(sql, name = nil)
          select(sql, name)
        end

        def select_one(sql, name = nil)
          select(sql, name).first
        end

        def insert(sql, name = nil, pk = nil, id_value = nil)
          execute(sql, name = nil)
          id_value || last_insert_id
        end

        def execute(sql, name = nil)
          rows_affected = 0

          log(sql, name, @connection) do |connection| 
            stmt = DB2::Statement.new(connection)
            stmt.exec_direct(sql)
            rows_affected = stmt.row_count
            stmt.free
          end

          rows_affected
        end

        alias_method :update, :execute
        alias_method :delete, :execute

        def begin_db_transaction
          @connection.set_auto_commit_off
        end

        def commit_db_transaction
          @connection.commit
          @connection.set_auto_commit_on
        end
        
        def rollback_db_transaction
          @connection.rollback
          @connection.set_auto_commit_on
        end

        def quote_column_name(name) name; end

        def adapter_name()
          'DB2'
        end

        def quote_string(s)
          s.gsub(/'/, "''") # ' (for ruby-mode)
        end

        def add_limit!(sql, limit)
          sql << " FETCH FIRST #{limit} ROWS ONLY"
        end

        def columns(table_name, name = nil)
          stmt = DB2::Statement.new(@connection)
          result = []

          stmt.columns(table_name.upcase).each do |c| 
            c_name = c[3].downcase
            c_default = c[12] == 'NULL' ? nil : c[12]
            c_type = c[5].downcase
            c_type += "(#{c[6]})" if !c[6].nil? && c[6] != ''
            result << Column.new(c_name, c_default, c_type)
          end 

          stmt.free
          result
        end

        private

        def last_insert_id
          row = select_one(<<-GETID.strip)
          with temp(id) as (values (identity_val_local())) select * from temp
          GETID
          row['id'].to_i
        end

        def select(sql, name = nil)
          stmt = nil
          log(sql, name, @connection) do |connection|
            stmt = DB2::Statement.new(connection)
            stmt.exec_direct(sql + " with ur")
          end

          rows = []
          while row = stmt.fetch_as_hash
            rows << row
          end
          stmt.free
          rows
        end
      end
    end
  end
rescue LoadError
  # DB2 driver is unavailable.
end