File: oracle.rb

package info (click to toggle)
ruby-sequel 5.63.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 10,408 kB
  • sloc: ruby: 113,747; makefile: 3
file content (146 lines) | stat: -rw-r--r-- 4,170 bytes parent folder | download | duplicates (3)
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
# frozen-string-literal: true

Sequel::JDBC.load_driver('Java::oracle.jdbc.driver.OracleDriver')
require_relative '../shared/oracle'
require_relative 'transactions'

module Sequel
  module JDBC
    Sequel.synchronize do
      DATABASE_SETUP[:oracle] = proc do |db|
        db.extend(Sequel::JDBC::Oracle::DatabaseMethods)
        db.dataset_class = Sequel::JDBC::Oracle::Dataset
        Java::oracle.jdbc.driver.OracleDriver
      end
    end

    module Oracle
      JAVA_BIG_DECIMAL_CONSTRUCTOR = java.math.BigDecimal.java_class.constructor(Java::long).method(:new_instance)
      ORACLE_DECIMAL = Object.new
      def ORACLE_DECIMAL.call(r, i)
        if v = r.getBigDecimal(i)
          i = v.long_value
          if v == JAVA_BIG_DECIMAL_CONSTRUCTOR.call(i)
            i
          else
            ::Kernel::BigDecimal(v.to_string)
          end
        end
      end 

      ORACLE_CLOB = Object.new
      def ORACLE_CLOB.call(r, i)
        return unless clob = r.getClob(i)
        str = clob.getSubString(1, clob.length)
        clob.freeTemporary if clob.isTemporary
        str
      end

      module DatabaseMethods
        include Sequel::Oracle::DatabaseMethods
        include Sequel::JDBC::Transactions

        def self.extended(db)
          db.instance_exec do
            @autosequence = opts[:autosequence]
            @primary_key_sequences = {}
          end
        end
        
        private

        # Oracle exception handling with SQLState is less accurate than with regexps.
        def database_exception_use_sqlstates?
          false
        end

        def disconnect_error?(exception, opts)
          super || exception.message =~ /\AClosed Connection/
        end

        # Default the fetch size for statements to 100, similar to the oci8-based oracle adapter.
        def default_fetch_size
          100
        end
        
        def last_insert_id(conn, opts)
          unless sequence = opts[:sequence]
            if t = opts[:table]
              sequence = sequence_for_table(t)
            end
          end
          if sequence
            sql = "SELECT #{literal(sequence)}.currval FROM dual"
            statement(conn) do |stmt|
              begin
                rs = log_connection_yield(sql, conn){stmt.executeQuery(sql)}
                rs.next
                rs.getLong(1)
              rescue java.sql.SQLException
                nil
              end
            end
          end
        end

        # Primary key indexes appear to start with sys_ on Oracle
        def primary_key_index_re
          /\Asys_/i
        end

        def schema_parse_table(*)
          sch = super
          sch.each do |c, s|
            if s[:type] == :decimal && s[:scale] == -127
              s[:type] = :integer
            elsif s[:db_type] == 'DATE'
              s[:type] = :datetime
            end
          end
          sch
        end

        def schema_parse_table_skip?(h, schema)
          super || (h[:table_schem] != current_user unless schema)
        end

        # As of Oracle 9.2, releasing savepoints is no longer supported.
        def supports_releasing_savepoints?
          false
        end

        def setup_type_convertor_map
          super
          @type_convertor_map[:OracleDecimal] = ORACLE_DECIMAL
          @type_convertor_map[:OracleClob] = ORACLE_CLOB
        end
      end
      
      class Dataset < JDBC::Dataset
        include Sequel::Oracle::DatasetMethods

        NUMERIC_TYPE = Java::JavaSQL::Types::NUMERIC
        TIMESTAMP_TYPE = Java::JavaSQL::Types::TIMESTAMP
        CLOB_TYPE = Java::JavaSQL::Types::CLOB
        TIMESTAMPTZ_TYPES = [Java::oracle.jdbc.OracleTypes::TIMESTAMPTZ, Java::oracle.jdbc.OracleTypes::TIMESTAMPLTZ].freeze

        def type_convertor(map, meta, type, i)
          case type
          when NUMERIC_TYPE
            if meta.getScale(i) == 0
              map[:OracleDecimal]
            else
              super
            end
          when *TIMESTAMPTZ_TYPES
            map[TIMESTAMP_TYPE]
          when CLOB_TYPE 
            map[:OracleClob]
          else
            super
          end
        end
      end
    end
  end
end